Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(193)

Side by Side Diff: content/browser/gpu/browser_gpu_memory_buffer_manager.cc

Issue 1055403010: content: Add GpuMemoryBuffer MemoryDumpProvider implementation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: save register of dump provider to follow up patch Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "content/browser/gpu/browser_gpu_memory_buffer_manager.h" 5 #include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
6 6
7 #include "base/atomic_sequence_num.h" 7 #include "base/atomic_sequence_num.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/lazy_instance.h" 9 #include "base/lazy_instance.h"
10 #include "base/strings/stringprintf.h"
10 #include "base/synchronization/waitable_event.h" 11 #include "base/synchronization/waitable_event.h"
11 #include "base/threading/thread_restrictions.h" 12 #include "base/threading/thread_restrictions.h"
13 #include "base/trace_event/process_memory_dump.h"
12 #include "base/trace_event/trace_event.h" 14 #include "base/trace_event/trace_event.h"
13 #include "content/common/gpu/client/gpu_memory_buffer_factory_host.h" 15 #include "content/common/gpu/client/gpu_memory_buffer_factory_host.h"
14 #include "content/common/gpu/client/gpu_memory_buffer_impl.h" 16 #include "content/common/gpu/client/gpu_memory_buffer_impl.h"
15 #include "content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h" 17 #include "content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h"
16 #include "content/public/browser/browser_thread.h" 18 #include "content/public/browser/browser_thread.h"
17 19
18 namespace content { 20 namespace content {
19 namespace { 21 namespace {
20 22
21 BrowserGpuMemoryBufferManager* g_gpu_memory_buffer_manager = nullptr; 23 BrowserGpuMemoryBufferManager* g_gpu_memory_buffer_manager = nullptr;
22 24
23 // Global atomic to generate gpu memory buffer unique IDs. 25 // Global atomic to generate gpu memory buffer unique IDs.
24 base::StaticAtomicSequenceNumber g_next_gpu_memory_buffer_id; 26 base::StaticAtomicSequenceNumber g_next_gpu_memory_buffer_id;
25 27
28 const char kMemoryAllocatorName[] = "gpumemorybuffer";
29
30 const char kMemoryAllocatorHeapNamePrefix[] = "buffer";
31
32 const char kMemoryDumpProviderFriendlyName[] = "GpuMemoryBuffer";
33
26 } // namespace 34 } // namespace
27 35
28 struct BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferRequest { 36 struct BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferRequest {
29 AllocateGpuMemoryBufferRequest(const gfx::Size& size, 37 AllocateGpuMemoryBufferRequest(const gfx::Size& size,
30 gfx::GpuMemoryBuffer::Format format, 38 gfx::GpuMemoryBuffer::Format format,
31 gfx::GpuMemoryBuffer::Usage usage, 39 gfx::GpuMemoryBuffer::Usage usage,
32 int client_id, 40 int client_id,
33 int surface_id) 41 int surface_id)
34 : event(true, false), 42 : event(true, false),
35 size(size), 43 size(size),
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 if (!gpu_memory_buffer_factory_host_->IsGpuMemoryBufferConfigurationSupported( 146 if (!gpu_memory_buffer_factory_host_->IsGpuMemoryBufferConfigurationSupported(
139 format, usage)) { 147 format, usage)) {
140 // Early out if we cannot fallback to shared memory buffer. 148 // Early out if we cannot fallback to shared memory buffer.
141 if (!GpuMemoryBufferImplSharedMemory::IsFormatSupported(format) || 149 if (!GpuMemoryBufferImplSharedMemory::IsFormatSupported(format) ||
142 !GpuMemoryBufferImplSharedMemory::IsSizeValidForFormat(size, format) || 150 !GpuMemoryBufferImplSharedMemory::IsSizeValidForFormat(size, format) ||
143 usage != gfx::GpuMemoryBuffer::MAP) { 151 usage != gfx::GpuMemoryBuffer::MAP) {
144 callback.Run(gfx::GpuMemoryBufferHandle()); 152 callback.Run(gfx::GpuMemoryBufferHandle());
145 return; 153 return;
146 } 154 }
147 155
148 buffers[new_id] = gfx::SHARED_MEMORY_BUFFER; 156 buffers[new_id] = BufferInfo(size, format, gfx::SHARED_MEMORY_BUFFER);
149 callback.Run(GpuMemoryBufferImplSharedMemory::AllocateForChildProcess( 157 callback.Run(GpuMemoryBufferImplSharedMemory::AllocateForChildProcess(
150 new_id, size, format, child_process_handle)); 158 new_id, size, format, child_process_handle));
151 return; 159 return;
152 } 160 }
153 161
154 // Note: Handling of cases where the child process is removed before the 162 // Note: Handling of cases where the child process is removed before the
155 // allocation completes is less subtle if we set the buffer type to 163 // allocation completes is less subtle if we set the buffer type to
156 // EMPTY_BUFFER here and verify that this has not changed when allocation 164 // EMPTY_BUFFER here and verify that this has not changed when allocation
157 // completes. 165 // completes.
158 buffers[new_id] = gfx::EMPTY_BUFFER; 166 buffers[new_id] = BufferInfo(size, format, gfx::EMPTY_BUFFER);
159 167
160 gpu_memory_buffer_factory_host_->CreateGpuMemoryBuffer( 168 gpu_memory_buffer_factory_host_->CreateGpuMemoryBuffer(
161 new_id, size, format, usage, child_client_id, 0, 169 new_id, size, format, usage, child_client_id, 0,
162 base::Bind(&BrowserGpuMemoryBufferManager:: 170 base::Bind(&BrowserGpuMemoryBufferManager::
163 GpuMemoryBufferAllocatedForChildProcess, 171 GpuMemoryBufferAllocatedForChildProcess,
164 weak_ptr_factory_.GetWeakPtr(), child_client_id, callback)); 172 weak_ptr_factory_.GetWeakPtr(), child_client_id, callback));
165 } 173 }
166 174
167 gfx::GpuMemoryBuffer* 175 gfx::GpuMemoryBuffer*
168 BrowserGpuMemoryBufferManager::GpuMemoryBufferFromClientBuffer( 176 BrowserGpuMemoryBufferManager::GpuMemoryBufferFromClientBuffer(
169 ClientBuffer buffer) { 177 ClientBuffer buffer) {
170 return GpuMemoryBufferImpl::FromClientBuffer(buffer); 178 return GpuMemoryBufferImpl::FromClientBuffer(buffer);
171 } 179 }
172 180
173 void BrowserGpuMemoryBufferManager::SetDestructionSyncPoint( 181 void BrowserGpuMemoryBufferManager::SetDestructionSyncPoint(
174 gfx::GpuMemoryBuffer* buffer, 182 gfx::GpuMemoryBuffer* buffer,
175 uint32 sync_point) { 183 uint32 sync_point) {
176 static_cast<GpuMemoryBufferImpl*>(buffer) 184 static_cast<GpuMemoryBufferImpl*>(buffer)
177 ->set_destruction_sync_point(sync_point); 185 ->set_destruction_sync_point(sync_point);
178 } 186 }
179 187
188 bool BrowserGpuMemoryBufferManager::DumpInto(
189 base::trace_event::ProcessMemoryDump* pmd) {
190 DCHECK_CURRENTLY_ON(BrowserThread::IO);
191
192 for (auto& client_it : clients_) {
193 for (auto& buffer_it : client_it.second) {
194 if (buffer_it.second.type == gfx::EMPTY_BUFFER)
195 continue;
196
197 std::string heap_name = base::StringPrintf(
198 "%s%d", kMemoryAllocatorHeapNamePrefix, buffer_it.first);
199 base::trace_event::MemoryAllocatorDump* dump =
200 pmd->CreateAllocatorDump(kMemoryAllocatorName, heap_name.c_str());
201 if (!dump)
202 return false;
203
204 size_t buffer_size_in_bytes = 0;
205 // Note: BufferSizeInBytes returns an approximated size for the buffer
206 // but the factory can be made to return the exact size if this
207 // approximation is not good enough.
208 bool valid_size = GpuMemoryBufferImpl::BufferSizeInBytes(
209 buffer_it.second.size, buffer_it.second.format,
210 &buffer_size_in_bytes);
211 DCHECK(valid_size);
212
213 dump->set_physical_size_in_bytes(buffer_size_in_bytes);
214 dump->set_allocated_objects_count(1);
215 dump->set_allocated_objects_size_in_bytes(buffer_size_in_bytes);
216 }
217 }
218
219 return true;
220 }
221
222 const char* BrowserGpuMemoryBufferManager::GetFriendlyName() const {
223 return kMemoryDumpProviderFriendlyName;
224 }
225
180 void BrowserGpuMemoryBufferManager::ChildProcessDeletedGpuMemoryBuffer( 226 void BrowserGpuMemoryBufferManager::ChildProcessDeletedGpuMemoryBuffer(
181 gfx::GpuMemoryBufferId id, 227 gfx::GpuMemoryBufferId id,
182 base::ProcessHandle child_process_handle, 228 base::ProcessHandle child_process_handle,
183 int child_client_id, 229 int child_client_id,
184 uint32 sync_point) { 230 uint32 sync_point) {
185 DCHECK_CURRENTLY_ON(BrowserThread::IO); 231 DCHECK_CURRENTLY_ON(BrowserThread::IO);
186 DCHECK(clients_.find(child_client_id) != clients_.end()); 232 DCHECK(clients_.find(child_client_id) != clients_.end());
187 233
188 BufferMap& buffers = clients_[child_client_id]; 234 BufferMap& buffers = clients_[child_client_id];
189 235
190 BufferMap::iterator buffer_it = buffers.find(id); 236 BufferMap::iterator buffer_it = buffers.find(id);
191 if (buffer_it == buffers.end()) { 237 if (buffer_it == buffers.end()) {
192 LOG(ERROR) << "Invalid GpuMemoryBuffer ID for child process."; 238 LOG(ERROR) << "Invalid GpuMemoryBuffer ID for child process.";
193 return; 239 return;
194 } 240 }
195 241
196 // This can happen if a child process managed to trigger a call to this while 242 // This can happen if a child process managed to trigger a call to this while
197 // a buffer is in the process of being allocated. 243 // a buffer is in the process of being allocated.
198 if (buffer_it->second == gfx::EMPTY_BUFFER) { 244 if (buffer_it->second.type == gfx::EMPTY_BUFFER) {
199 LOG(ERROR) << "Invalid GpuMemoryBuffer type."; 245 LOG(ERROR) << "Invalid GpuMemoryBuffer type.";
200 return; 246 return;
201 } 247 }
202 248
203 // Buffers allocated using the factory need to be destroyed through the 249 // Buffers allocated using the factory need to be destroyed through the
204 // factory. 250 // factory.
205 if (buffer_it->second != gfx::SHARED_MEMORY_BUFFER) { 251 if (buffer_it->second.type != gfx::SHARED_MEMORY_BUFFER) {
206 gpu_memory_buffer_factory_host_->DestroyGpuMemoryBuffer(id, 252 gpu_memory_buffer_factory_host_->DestroyGpuMemoryBuffer(id,
207 child_client_id, 253 child_client_id,
208 sync_point); 254 sync_point);
209 } 255 }
210 256
211 buffers.erase(buffer_it); 257 buffers.erase(buffer_it);
212 } 258 }
213 259
214 void BrowserGpuMemoryBufferManager::ProcessRemoved( 260 void BrowserGpuMemoryBufferManager::ProcessRemoved(
215 base::ProcessHandle process_handle, 261 base::ProcessHandle process_handle,
216 int client_id) { 262 int client_id) {
217 DCHECK_CURRENTLY_ON(BrowserThread::IO); 263 DCHECK_CURRENTLY_ON(BrowserThread::IO);
218 264
219 ClientMap::iterator client_it = clients_.find(client_id); 265 ClientMap::iterator client_it = clients_.find(client_id);
220 if (client_it == clients_.end()) 266 if (client_it == clients_.end())
221 return; 267 return;
222 268
223 for (auto &buffer_it : client_it->second) { 269 for (auto &buffer_it : client_it->second) {
224 // This might happen if buffer is currenlty in the process of being 270 // This might happen if buffer is currenlty in the process of being
225 // allocated. The buffer will in that case be cleaned up when allocation 271 // allocated. The buffer will in that case be cleaned up when allocation
226 // completes. 272 // completes.
227 if (buffer_it.second == gfx::EMPTY_BUFFER) 273 if (buffer_it.second.type == gfx::EMPTY_BUFFER)
228 continue; 274 continue;
229 275
230 // Skip shared memory buffers as they were not allocated using the factory. 276 // Skip shared memory buffers as they were not allocated using the factory.
231 if (buffer_it.second == gfx::SHARED_MEMORY_BUFFER) 277 if (buffer_it.second.type == gfx::SHARED_MEMORY_BUFFER)
232 continue; 278 continue;
233 279
234 gpu_memory_buffer_factory_host_->DestroyGpuMemoryBuffer(buffer_it.first, 280 gpu_memory_buffer_factory_host_->DestroyGpuMemoryBuffer(buffer_it.first,
235 client_id, 281 client_id,
236 0); 282 0);
237 } 283 }
238 284
239 clients_.erase(client_it); 285 clients_.erase(client_it);
240 } 286 }
241 287
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 handle.id, child_client_id, 0); 344 handle.id, child_client_id, 0);
299 } 345 }
300 callback.Run(gfx::GpuMemoryBufferHandle()); 346 callback.Run(gfx::GpuMemoryBufferHandle());
301 return; 347 return;
302 } 348 }
303 349
304 BufferMap& buffers = client_it->second; 350 BufferMap& buffers = client_it->second;
305 351
306 BufferMap::iterator buffer_it = buffers.find(handle.id); 352 BufferMap::iterator buffer_it = buffers.find(handle.id);
307 DCHECK(buffer_it != buffers.end()); 353 DCHECK(buffer_it != buffers.end());
308 DCHECK_EQ(buffer_it->second, gfx::EMPTY_BUFFER); 354 DCHECK_EQ(buffer_it->second.type, gfx::EMPTY_BUFFER);
309 355
310 if (handle.is_null()) { 356 if (handle.is_null()) {
311 buffers.erase(buffer_it); 357 buffers.erase(buffer_it);
312 callback.Run(gfx::GpuMemoryBufferHandle()); 358 callback.Run(gfx::GpuMemoryBufferHandle());
313 return; 359 return;
314 } 360 }
315 361
316 // The factory should never return a shared memory backed buffer. 362 // The factory should never return a shared memory backed buffer.
317 DCHECK_NE(handle.type, gfx::SHARED_MEMORY_BUFFER); 363 DCHECK_NE(handle.type, gfx::SHARED_MEMORY_BUFFER);
318 364
319 // Store the type of this buffer so it can be cleaned up if the child 365 // Store the type of this buffer so it can be cleaned up if the child
320 // process is removed. 366 // process is removed.
321 buffer_it->second = handle.type; 367 buffer_it->second.type = handle.type;
322 368
323 callback.Run(handle); 369 callback.Run(handle);
324 } 370 }
325 371
326 } // namespace content 372 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698