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

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

Issue 1189943002: content: Fix lost context handling when using native GpuMemoryBuffers. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix tests Created 5 years, 6 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/command_line.h"
10 #include "base/lazy_instance.h"
9 #include "base/strings/stringprintf.h" 11 #include "base/strings/stringprintf.h"
10 #include "base/synchronization/waitable_event.h" 12 #include "base/synchronization/waitable_event.h"
11 #include "base/threading/thread_restrictions.h" 13 #include "base/threading/thread_restrictions.h"
12 #include "base/trace_event/process_memory_dump.h" 14 #include "base/trace_event/process_memory_dump.h"
13 #include "base/trace_event/trace_event.h" 15 #include "base/trace_event/trace_event.h"
14 #include "content/common/gpu/client/gpu_memory_buffer_factory_host.h" 16 #include "content/browser/gpu/browser_gpu_channel_host_factory.h"
17 #include "content/browser/gpu/gpu_process_host.h"
15 #include "content/common/gpu/client/gpu_memory_buffer_impl.h" 18 #include "content/common/gpu/client/gpu_memory_buffer_impl.h"
16 #include "content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h" 19 #include "content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h"
20 #include "content/common/gpu/gpu_memory_buffer_factory_shared_memory.h"
17 #include "content/public/browser/browser_thread.h" 21 #include "content/public/browser/browser_thread.h"
22 #include "content/public/common/content_switches.h"
23 #include "gpu/GLES2/gl2extchromium.h"
24
25 #if defined(OS_MACOSX)
26 #include "content/common/gpu/gpu_memory_buffer_factory_io_surface.h"
27 #endif
28
29 #if defined(OS_ANDROID)
30 #include "content/common/gpu/gpu_memory_buffer_factory_surface_texture.h"
31 #endif
32
33 #if defined(USE_OZONE)
34 #include "content/common/gpu/gpu_memory_buffer_factory_ozone_native_buffer.h"
35 #endif
18 36
19 namespace content { 37 namespace content {
20 namespace { 38 namespace {
21 39
22 BrowserGpuMemoryBufferManager* g_gpu_memory_buffer_manager = nullptr; 40 bool IsGpuMemoryBufferFactoryConfigurationSupported(
41 gfx::GpuMemoryBufferType type,
42 const GpuMemoryBufferFactory::Configuration& configuration) {
43 switch (type) {
44 case gfx::SHARED_MEMORY_BUFFER:
45 return GpuMemoryBufferFactorySharedMemory::
46 IsGpuMemoryBufferConfigurationSupported(configuration.format,
47 configuration.usage);
48 #if defined(OS_MACOSX)
49 case gfx::IO_SURFACE_BUFFER:
50 return GpuMemoryBufferFactoryIOSurface::
51 IsGpuMemoryBufferConfigurationSupported(configuration.format,
52 configuration.usage);
53 #endif
54 #if defined(OS_ANDROID)
55 case gfx::SURFACE_TEXTURE_BUFFER:
56 return GpuMemoryBufferFactorySurfaceTexture::
57 IsGpuMemoryBufferConfigurationSupported(configuration.format,
58 configuration.usage);
59 #endif
60 #if defined(USE_OZONE)
61 case gfx::OZONE_NATIVE_BUFFER:
62 return GpuMemoryBufferFactoryOzoneNativeBuffer::
63 IsGpuMemoryBufferConfigurationSupported(configuration.format,
64 configuration.usage);
65 #endif
66 default:
67 NOTREACHED();
68 return false;
69 }
70 }
71
72 gfx::GpuMemoryBufferType GetGpuMemoryBufferFactoryType() {
73 std::vector<gfx::GpuMemoryBufferType> supported_types;
74 GpuMemoryBufferFactory::GetSupportedTypes(&supported_types);
75 DCHECK(!supported_types.empty());
76
77 // The GPU service will always use the preferred type.
78 return supported_types[0];
79 }
23 80
24 // Global atomic to generate gpu memory buffer unique IDs. 81 // Global atomic to generate gpu memory buffer unique IDs.
25 base::StaticAtomicSequenceNumber g_next_gpu_memory_buffer_id; 82 base::StaticAtomicSequenceNumber g_next_gpu_memory_buffer_id;
26 83
27 const char kMemoryAllocatorName[] = "gpumemorybuffer"; 84 const char kMemoryAllocatorName[] = "gpumemorybuffer";
28 85
86 base::LazyInstance<BrowserGpuMemoryBufferManager>::Leaky
piman 2015/06/19 19:29:48 I'm not crazy about leaving this Leaky, because it
reveman 2015/06/22 17:09:12 Makes sense. Done.
87 g_gpu_memory_buffer_manager = LAZY_INSTANCE_INITIALIZER;
88
29 } // namespace 89 } // namespace
30 90
31 struct BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferRequest { 91 struct BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferRequest {
32 AllocateGpuMemoryBufferRequest(const gfx::Size& size, 92 AllocateGpuMemoryBufferRequest(const gfx::Size& size,
33 gfx::GpuMemoryBuffer::Format format, 93 gfx::GpuMemoryBuffer::Format format,
34 gfx::GpuMemoryBuffer::Usage usage, 94 gfx::GpuMemoryBuffer::Usage usage,
35 int client_id, 95 int client_id,
36 int surface_id) 96 int surface_id)
37 : event(true, false), 97 : event(true, false),
38 size(size), 98 size(size),
39 format(format), 99 format(format),
40 usage(usage), 100 usage(usage),
41 client_id(client_id), 101 client_id(client_id),
42 surface_id(surface_id) {} 102 surface_id(surface_id) {}
43 ~AllocateGpuMemoryBufferRequest() {} 103 ~AllocateGpuMemoryBufferRequest() {}
44 base::WaitableEvent event; 104 base::WaitableEvent event;
45 gfx::Size size; 105 gfx::Size size;
46 gfx::GpuMemoryBuffer::Format format; 106 gfx::GpuMemoryBuffer::Format format;
47 gfx::GpuMemoryBuffer::Usage usage; 107 gfx::GpuMemoryBuffer::Usage usage;
48 int client_id; 108 int client_id;
49 int surface_id; 109 int surface_id;
50 scoped_ptr<gfx::GpuMemoryBuffer> result; 110 scoped_ptr<gfx::GpuMemoryBuffer> result;
51 }; 111 };
52 112
53 BrowserGpuMemoryBufferManager::BrowserGpuMemoryBufferManager( 113 BrowserGpuMemoryBufferManager::BrowserGpuMemoryBufferManager()
54 GpuMemoryBufferFactoryHost* gpu_memory_buffer_factory_host, 114 : factory_type_(GetGpuMemoryBufferFactoryType()),
55 int gpu_client_id) 115 supported_configurations_(
56 : gpu_memory_buffer_factory_host_(gpu_memory_buffer_factory_host), 116 GetSupportedGpuMemoryBufferConfigurations(factory_type_)),
57 gpu_client_id_(gpu_client_id), 117 gpu_host_id_(0) {
58 weak_ptr_factory_(this) {
59 DCHECK(!g_gpu_memory_buffer_manager);
60 g_gpu_memory_buffer_manager = this;
61 } 118 }
62 119
63 BrowserGpuMemoryBufferManager::~BrowserGpuMemoryBufferManager() { 120 BrowserGpuMemoryBufferManager::~BrowserGpuMemoryBufferManager() {
64 g_gpu_memory_buffer_manager = nullptr;
65 } 121 }
66 122
67 // static 123 // static
68 BrowserGpuMemoryBufferManager* BrowserGpuMemoryBufferManager::current() { 124 BrowserGpuMemoryBufferManager* BrowserGpuMemoryBufferManager::current() {
69 return g_gpu_memory_buffer_manager; 125 return g_gpu_memory_buffer_manager.Pointer();
70 } 126 }
71 127
72 scoped_ptr<gfx::GpuMemoryBuffer> 128 scoped_ptr<gfx::GpuMemoryBuffer>
73 BrowserGpuMemoryBufferManager::AllocateGpuMemoryBuffer( 129 BrowserGpuMemoryBufferManager::AllocateGpuMemoryBuffer(
74 const gfx::Size& size, 130 const gfx::Size& size,
75 gfx::GpuMemoryBuffer::Format format, 131 gfx::GpuMemoryBuffer::Format format,
76 gfx::GpuMemoryBuffer::Usage usage) { 132 gfx::GpuMemoryBuffer::Usage usage) {
77 return AllocateGpuMemoryBufferCommon(size, format, usage, 0); 133 return AllocateGpuMemoryBufferForSurface(size, format, usage, 0);
78 } 134 }
79 135
80 scoped_ptr<gfx::GpuMemoryBuffer> 136 scoped_ptr<gfx::GpuMemoryBuffer>
81 BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForScanout( 137 BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForScanout(
82 const gfx::Size& size, 138 const gfx::Size& size,
83 gfx::GpuMemoryBuffer::Format format, 139 gfx::GpuMemoryBuffer::Format format,
84 int32 surface_id) { 140 int32 surface_id) {
85 DCHECK_GT(surface_id, 0); 141 DCHECK_GT(surface_id, 0);
86 return AllocateGpuMemoryBufferCommon( 142 return AllocateGpuMemoryBufferForSurface(
87 size, format, gfx::GpuMemoryBuffer::SCANOUT, surface_id); 143 size, format, gfx::GpuMemoryBuffer::SCANOUT, surface_id);
88 } 144 }
89 145
90 scoped_ptr<gfx::GpuMemoryBuffer>
91 BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferCommon(
92 const gfx::Size& size,
93 gfx::GpuMemoryBuffer::Format format,
94 gfx::GpuMemoryBuffer::Usage usage,
95 int32 surface_id) {
96 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
97
98 // Fallback to shared memory buffer if |format| and |usage| are not supported
99 // by factory.
100 if (!gpu_memory_buffer_factory_host_->IsGpuMemoryBufferConfigurationSupported(
101 format, usage)) {
102 DCHECK(GpuMemoryBufferImplSharedMemory::IsFormatSupported(format))
103 << format;
104 DCHECK(GpuMemoryBufferImplSharedMemory::IsUsageSupported(usage)) << usage;
105 return GpuMemoryBufferImplSharedMemory::Create(
106 g_next_gpu_memory_buffer_id.GetNext(), size, format);
107 }
108
109 AllocateGpuMemoryBufferRequest request(size, format, usage, gpu_client_id_,
110 surface_id);
111 BrowserThread::PostTask(
112 BrowserThread::IO,
113 FROM_HERE,
114 base::Bind(&BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferOnIO,
115 base::Unretained(this), // Safe as we wait for result below.
116 base::Unretained(&request)));
117
118 // We're blocking the UI thread, which is generally undesirable.
119 TRACE_EVENT0("browser",
120 "BrowserGpuMemoryBufferManager::AllocateGpuMemoryBuffer");
121 base::ThreadRestrictions::ScopedAllowWait allow_wait;
122 request.event.Wait();
123 return request.result.Pass();
124 }
125
126 void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForChildProcess( 146 void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForChildProcess(
127 const gfx::Size& size, 147 const gfx::Size& size,
128 gfx::GpuMemoryBuffer::Format format, 148 gfx::GpuMemoryBuffer::Format format,
129 gfx::GpuMemoryBuffer::Usage usage, 149 gfx::GpuMemoryBuffer::Usage usage,
130 base::ProcessHandle child_process_handle, 150 base::ProcessHandle child_process_handle,
131 int child_client_id, 151 int child_client_id,
132 const AllocationCallback& callback) { 152 const AllocationCallback& callback) {
133 DCHECK_CURRENTLY_ON(BrowserThread::IO); 153 DCHECK_CURRENTLY_ON(BrowserThread::IO);
134 154
135 gfx::GpuMemoryBufferId new_id = g_next_gpu_memory_buffer_id.GetNext(); 155 gfx::GpuMemoryBufferId new_id = g_next_gpu_memory_buffer_id.GetNext();
136 156
157 // Use service side allocation if this is a supported configuration.
158 if (IsGpuMemoryBufferConfigurationSupported(format, usage)) {
159 AllocateGpuMemoryBufferOnIO(new_id, size, format, usage, child_client_id, 0,
160 callback);
161 return;
162 }
163
164 // Early out if we cannot fallback to shared memory buffer.
165 if (!GpuMemoryBufferImplSharedMemory::IsFormatSupported(format) ||
166 !GpuMemoryBufferImplSharedMemory::IsUsageSupported(usage) ||
167 !GpuMemoryBufferImplSharedMemory::IsSizeValidForFormat(size, format)) {
168 callback.Run(gfx::GpuMemoryBufferHandle());
169 return;
170 }
171
137 BufferMap& buffers = clients_[child_client_id]; 172 BufferMap& buffers = clients_[child_client_id];
138 DCHECK(buffers.find(new_id) == buffers.end()); 173 DCHECK(buffers.find(new_id) == buffers.end());
139 174
140 // Fallback to shared memory buffer if |format| and |usage| are not supported 175 // Allocate shared memory buffer as fallback.
141 // by factory. 176 buffers[new_id] = BufferInfo(size, format, gfx::SHARED_MEMORY_BUFFER, 0);
142 if (!gpu_memory_buffer_factory_host_->IsGpuMemoryBufferConfigurationSupported( 177 callback.Run(GpuMemoryBufferImplSharedMemory::AllocateForChildProcess(
143 format, usage)) { 178 new_id, size, format, child_process_handle));
144 // Early out if we cannot fallback to shared memory buffer.
145 if (!GpuMemoryBufferImplSharedMemory::IsFormatSupported(format) ||
146 !GpuMemoryBufferImplSharedMemory::IsUsageSupported(usage) ||
147 !GpuMemoryBufferImplSharedMemory::IsSizeValidForFormat(size, format)) {
148 callback.Run(gfx::GpuMemoryBufferHandle());
149 return;
150 }
151
152 buffers[new_id] = BufferInfo(size, format, gfx::SHARED_MEMORY_BUFFER);
153 callback.Run(GpuMemoryBufferImplSharedMemory::AllocateForChildProcess(
154 new_id, size, format, child_process_handle));
155 return;
156 }
157
158 // Note: Handling of cases where the child process is removed before the
159 // allocation completes is less subtle if we set the buffer type to
160 // EMPTY_BUFFER here and verify that this has not changed when allocation
161 // completes.
162 buffers[new_id] = BufferInfo(size, format, gfx::EMPTY_BUFFER);
163
164 gpu_memory_buffer_factory_host_->CreateGpuMemoryBuffer(
165 new_id, size, format, usage, child_client_id, 0,
166 base::Bind(&BrowserGpuMemoryBufferManager::
167 GpuMemoryBufferAllocatedForChildProcess,
168 weak_ptr_factory_.GetWeakPtr(), new_id, child_client_id,
169 callback));
170 } 179 }
171 180
172 gfx::GpuMemoryBuffer* 181 gfx::GpuMemoryBuffer*
173 BrowserGpuMemoryBufferManager::GpuMemoryBufferFromClientBuffer( 182 BrowserGpuMemoryBufferManager::GpuMemoryBufferFromClientBuffer(
174 ClientBuffer buffer) { 183 ClientBuffer buffer) {
175 return GpuMemoryBufferImpl::FromClientBuffer(buffer); 184 return GpuMemoryBufferImpl::FromClientBuffer(buffer);
176 } 185 }
177 186
178 void BrowserGpuMemoryBufferManager::SetDestructionSyncPoint( 187 void BrowserGpuMemoryBufferManager::SetDestructionSyncPoint(
179 gfx::GpuMemoryBuffer* buffer, 188 gfx::GpuMemoryBuffer* buffer,
(...skipping 26 matching lines...) Expand all
206 215
207 dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, 216 dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
208 base::trace_event::MemoryAllocatorDump::kUnitsBytes, 217 base::trace_event::MemoryAllocatorDump::kUnitsBytes,
209 buffer_size_in_bytes); 218 buffer_size_in_bytes);
210 } 219 }
211 } 220 }
212 221
213 return true; 222 return true;
214 } 223 }
215 224
225 uint32 BrowserGpuMemoryBufferManager::GetImageTextureTarget(
226 gfx::GpuMemoryBuffer::Format format,
227 gfx::GpuMemoryBuffer::Usage usage) const {
228 if (!IsGpuMemoryBufferConfigurationSupported(format, usage))
229 return GL_TEXTURE_2D;
230
231 switch (factory_type_) {
232 case gfx::SURFACE_TEXTURE_BUFFER:
233 case gfx::OZONE_NATIVE_BUFFER:
234 // GPU memory buffers that are shared with the GL using EGLImages require
235 // TEXTURE_EXTERNAL_OES.
236 return GL_TEXTURE_EXTERNAL_OES;
237 case gfx::IO_SURFACE_BUFFER:
238 // IOSurface backed images require GL_TEXTURE_RECTANGLE_ARB.
239 return GL_TEXTURE_RECTANGLE_ARB;
240 default:
241 return GL_TEXTURE_2D;
242 }
243 }
244
216 void BrowserGpuMemoryBufferManager::ChildProcessDeletedGpuMemoryBuffer( 245 void BrowserGpuMemoryBufferManager::ChildProcessDeletedGpuMemoryBuffer(
217 gfx::GpuMemoryBufferId id, 246 gfx::GpuMemoryBufferId id,
218 base::ProcessHandle child_process_handle, 247 base::ProcessHandle child_process_handle,
219 int child_client_id, 248 int child_client_id,
220 uint32 sync_point) { 249 uint32 sync_point) {
221 DCHECK_CURRENTLY_ON(BrowserThread::IO); 250 DCHECK_CURRENTLY_ON(BrowserThread::IO);
222 DCHECK(clients_.find(child_client_id) != clients_.end());
223 251
224 BufferMap& buffers = clients_[child_client_id]; 252 DestroyGpuMemoryBufferOnIO(id, child_client_id, sync_point);
225
226 BufferMap::iterator buffer_it = buffers.find(id);
227 if (buffer_it == buffers.end()) {
228 LOG(ERROR) << "Invalid GpuMemoryBuffer ID for child process.";
229 return;
230 }
231
232 // This can happen if a child process managed to trigger a call to this while
233 // a buffer is in the process of being allocated.
234 if (buffer_it->second.type == gfx::EMPTY_BUFFER) {
235 LOG(ERROR) << "Invalid GpuMemoryBuffer type.";
236 return;
237 }
238
239 // Buffers allocated using the factory need to be destroyed through the
240 // factory.
241 if (buffer_it->second.type != gfx::SHARED_MEMORY_BUFFER) {
242 gpu_memory_buffer_factory_host_->DestroyGpuMemoryBuffer(id,
243 child_client_id,
244 sync_point);
245 }
246
247 buffers.erase(buffer_it);
248 } 253 }
249 254
250 void BrowserGpuMemoryBufferManager::ProcessRemoved( 255 void BrowserGpuMemoryBufferManager::ProcessRemoved(
251 base::ProcessHandle process_handle, 256 base::ProcessHandle process_handle,
252 int client_id) { 257 int client_id) {
253 DCHECK_CURRENTLY_ON(BrowserThread::IO); 258 DCHECK_CURRENTLY_ON(BrowserThread::IO);
254 259
255 ClientMap::iterator client_it = clients_.find(client_id); 260 ClientMap::iterator client_it = clients_.find(client_id);
256 if (client_it == clients_.end()) 261 if (client_it == clients_.end())
257 return; 262 return;
258 263
259 for (const auto& buffer : client_it->second) { 264 for (const auto& buffer : client_it->second) {
260 // This might happen if buffer is currenlty in the process of being 265 // This might happen if buffer is currenlty in the process of being
261 // allocated. The buffer will in that case be cleaned up when allocation 266 // allocated. The buffer will in that case be cleaned up when allocation
262 // completes. 267 // completes.
263 if (buffer.second.type == gfx::EMPTY_BUFFER) 268 if (buffer.second.type == gfx::EMPTY_BUFFER)
264 continue; 269 continue;
265 270
266 // Skip shared memory buffers as they were not allocated using the factory. 271 GpuProcessHost* host = GpuProcessHost::FromID(buffer.second.gpu_host_id);
267 if (buffer.second.type == gfx::SHARED_MEMORY_BUFFER) 272 if (host)
268 continue; 273 host->DestroyGpuMemoryBuffer(buffer.first, client_id, 0);
269
270 gpu_memory_buffer_factory_host_->DestroyGpuMemoryBuffer(buffer.first,
271 client_id, 0);
272 } 274 }
273 275
274 clients_.erase(client_it); 276 clients_.erase(client_it);
275 } 277 }
276 278
277 void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferOnIO( 279 // static
278 AllocateGpuMemoryBufferRequest* request) { 280 std::vector<GpuMemoryBufferFactory::Configuration>
279 // Note: Unretained is safe as this is only used for synchronous allocation 281 BrowserGpuMemoryBufferManager::GetSupportedGpuMemoryBufferConfigurations(
280 // from a non-IO thread. 282 gfx::GpuMemoryBufferType type) {
281 gpu_memory_buffer_factory_host_->CreateGpuMemoryBuffer( 283 std::vector<GpuMemoryBufferFactory::Configuration> configurations;
282 g_next_gpu_memory_buffer_id.GetNext(), request->size, request->format, 284 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
283 request->usage, request->client_id, request->surface_id, 285 switches::kEnableNativeGpuMemoryBuffers)) {
284 base::Bind(&BrowserGpuMemoryBufferManager::GpuMemoryBufferAllocatedOnIO, 286 const GpuMemoryBufferFactory::Configuration kNativeConfigurations[] = {
285 base::Unretained(this), base::Unretained(request))); 287 {gfx::GpuMemoryBuffer::R_8, gfx::GpuMemoryBuffer::MAP},
288 {gfx::GpuMemoryBuffer::R_8, gfx::GpuMemoryBuffer::PERSISTENT_MAP},
289 {gfx::GpuMemoryBuffer::RGBA_4444, gfx::GpuMemoryBuffer::MAP},
290 {gfx::GpuMemoryBuffer::RGBA_4444, gfx::GpuMemoryBuffer::PERSISTENT_MAP},
291 {gfx::GpuMemoryBuffer::RGBA_8888, gfx::GpuMemoryBuffer::MAP},
292 {gfx::GpuMemoryBuffer::RGBA_8888, gfx::GpuMemoryBuffer::PERSISTENT_MAP},
293 {gfx::GpuMemoryBuffer::BGRA_8888, gfx::GpuMemoryBuffer::MAP},
294 {gfx::GpuMemoryBuffer::BGRA_8888,
295 gfx::GpuMemoryBuffer::PERSISTENT_MAP}};
296 for (auto& configuration : kNativeConfigurations) {
297 if (IsGpuMemoryBufferFactoryConfigurationSupported(type, configuration))
298 configurations.push_back(configuration);
299 }
300 }
301
302 #if defined(USE_OZONE)
303 const GpuMemoryBufferFactory::Configuration kScanoutConfigurations[] = {
304 {gfx::GpuMemoryBuffer::BGRA_8888, gfx::GpuMemoryBuffer::SCANOUT},
305 {gfx::GpuMemoryBuffer::RGBX_8888, gfx::GpuMemoryBuffer::SCANOUT}};
306 for (auto& configuration : kScanoutConfigurations) {
307 if (IsGpuMemoryBufferFactoryConfigurationSupported(type, configuration))
308 configurations.push_back(configuration);
309 }
310 #endif
311
312 return configurations;
286 } 313 }
287 314
288 void BrowserGpuMemoryBufferManager::GpuMemoryBufferAllocatedOnIO( 315 scoped_ptr<gfx::GpuMemoryBuffer>
316 BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForSurface(
317 const gfx::Size& size,
318 gfx::GpuMemoryBuffer::Format format,
319 gfx::GpuMemoryBuffer::Usage usage,
320 int32 surface_id) {
321 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
322
323 AllocateGpuMemoryBufferRequest request(
324 size, format, usage,
325 BrowserGpuChannelHostFactory::instance()->GetGpuChannelId(), surface_id);
326 BrowserThread::PostTask(
327 BrowserThread::IO, FROM_HERE,
328 base::Bind(
329 &BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForSurfaceOnIO,
330 base::Unretained(this), base::Unretained(&request)));
331
332 // We're blocking the UI thread, which is generally undesirable.
333 TRACE_EVENT0(
334 "browser",
335 "BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForSurface");
336 base::ThreadRestrictions::ScopedAllowWait allow_wait;
337 request.event.Wait();
338 return request.result.Pass();
339 }
340
341 void BrowserGpuMemoryBufferManager::GpuMemoryBufferDeleted(
342 gfx::GpuMemoryBufferId id,
343 int client_id,
344 uint32 sync_point) {
345 BrowserThread::PostTask(
346 BrowserThread::IO, FROM_HERE,
347 base::Bind(&BrowserGpuMemoryBufferManager::DestroyGpuMemoryBufferOnIO,
348 base::Unretained(this), id, client_id, sync_point));
349 }
350
351 bool BrowserGpuMemoryBufferManager::IsGpuMemoryBufferConfigurationSupported(
352 gfx::GpuMemoryBuffer::Format format,
353 gfx::GpuMemoryBuffer::Usage usage) const {
354 for (auto& configuration : supported_configurations_) {
355 if (configuration.format == format && configuration.usage == usage)
356 return true;
357 }
358 return false;
359 }
360
361 void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForSurfaceOnIO(
362 AllocateGpuMemoryBufferRequest* request) {
363 DCHECK_CURRENTLY_ON(BrowserThread::IO);
364
365 gfx::GpuMemoryBufferId new_id = g_next_gpu_memory_buffer_id.GetNext();
366
367 // Use service side allocation if this is a supported configuration.
368 if (IsGpuMemoryBufferConfigurationSupported(request->format,
369 request->usage)) {
370 AllocateGpuMemoryBufferOnIO(
371 new_id, request->size, request->format, request->usage,
372 request->client_id, request->surface_id,
373 base::Bind(&BrowserGpuMemoryBufferManager::
374 GpuMemoryBufferAllocatedForSurfaceOnIO,
375 base::Unretained(this), base::Unretained(request)));
376 return;
377 }
378
379 DCHECK(GpuMemoryBufferImplSharedMemory::IsFormatSupported(request->format))
380 << request->format;
381 DCHECK(GpuMemoryBufferImplSharedMemory::IsUsageSupported(request->usage))
382 << request->usage;
383
384 BufferMap& buffers = clients_[request->client_id];
385 DCHECK(buffers.find(new_id) == buffers.end());
386
387 // Allocate shared memory buffer as fallback.
388 buffers[new_id] =
389 BufferInfo(request->size, request->format, gfx::SHARED_MEMORY_BUFFER, 0);
390 request->result = GpuMemoryBufferImplSharedMemory::Create(
391 new_id, request->size, request->format);
392 request->event.Signal();
393 }
394
395 void BrowserGpuMemoryBufferManager::GpuMemoryBufferAllocatedForSurfaceOnIO(
289 AllocateGpuMemoryBufferRequest* request, 396 AllocateGpuMemoryBufferRequest* request,
290 const gfx::GpuMemoryBufferHandle& handle) { 397 const gfx::GpuMemoryBufferHandle& handle) {
291 DCHECK_CURRENTLY_ON(BrowserThread::IO); 398 DCHECK_CURRENTLY_ON(BrowserThread::IO);
292 399
293 // Early out if factory failed to allocate the buffer. 400 // Early out if factory failed to allocate the buffer.
294 if (handle.is_null()) { 401 if (handle.is_null()) {
295 request->event.Signal(); 402 request->event.Signal();
296 return; 403 return;
297 } 404 }
298 405
299 DCHECK_NE(handle.type, gfx::SHARED_MEMORY_BUFFER);
300 request->result = GpuMemoryBufferImpl::CreateFromHandle( 406 request->result = GpuMemoryBufferImpl::CreateFromHandle(
301 handle, request->size, request->format, request->usage, 407 handle, request->size, request->format, request->usage,
302 base::Bind(&BrowserGpuMemoryBufferManager::GpuMemoryBufferDeleted, 408 base::Bind(&BrowserGpuMemoryBufferManager::GpuMemoryBufferDeleted,
303 weak_ptr_factory_.GetWeakPtr(), handle.id, 409 base::Unretained(this), handle.id, request->client_id));
304 request->client_id));
305 request->event.Signal(); 410 request->event.Signal();
306 } 411 }
307 412
308 void BrowserGpuMemoryBufferManager::GpuMemoryBufferDeleted( 413 void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferOnIO(
414 gfx::GpuMemoryBufferId id,
415 const gfx::Size& size,
416 gfx::GpuMemoryBuffer::Format format,
417 gfx::GpuMemoryBuffer::Usage usage,
418 int client_id,
419 int surface_id,
420 const AllocationCallback& callback) {
421 DCHECK_CURRENTLY_ON(BrowserThread::IO);
422
423 BufferMap& buffers = clients_[client_id];
424 DCHECK(buffers.find(id) == buffers.end());
425
426 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_);
427 if (!host) {
428 host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
429 CAUSE_FOR_GPU_LAUNCH_GPU_MEMORY_BUFFER_ALLOCATE);
430 if (!host) {
431 LOG(ERROR) << "Failed to launch GPU process.";
432 callback.Run(gfx::GpuMemoryBufferHandle());
433 return;
434 }
435 gpu_host_id_ = host->host_id();
436 }
437
438 // Note: Handling of cases where the client is removed before the allocation
439 // completes is less subtle if we set the buffer type to EMPTY_BUFFER here
440 // and verify that this has not changed when allocation completes.
441 buffers[id] = BufferInfo(size, format, gfx::EMPTY_BUFFER, 0);
442
443 host->CreateGpuMemoryBuffer(
444 id, size, format, usage, client_id, surface_id,
445 base::Bind(&BrowserGpuMemoryBufferManager::GpuMemoryBufferAllocatedOnIO,
446 base::Unretained(this), id, client_id, gpu_host_id_,
447 callback));
448 }
449
450 void BrowserGpuMemoryBufferManager::GpuMemoryBufferAllocatedOnIO(
309 gfx::GpuMemoryBufferId id, 451 gfx::GpuMemoryBufferId id,
310 int client_id, 452 int client_id,
311 uint32 sync_point) { 453 int gpu_host_id,
312 gpu_memory_buffer_factory_host_->DestroyGpuMemoryBuffer(id,
313 client_id,
314 sync_point);
315 }
316
317 void BrowserGpuMemoryBufferManager::GpuMemoryBufferAllocatedForChildProcess(
318 gfx::GpuMemoryBufferId id,
319 int child_client_id,
320 const AllocationCallback& callback, 454 const AllocationCallback& callback,
321 const gfx::GpuMemoryBufferHandle& handle) { 455 const gfx::GpuMemoryBufferHandle& handle) {
322 DCHECK_CURRENTLY_ON(BrowserThread::IO); 456 DCHECK_CURRENTLY_ON(BrowserThread::IO);
323 457
324 ClientMap::iterator client_it = clients_.find(child_client_id); 458 ClientMap::iterator client_it = clients_.find(client_id);
325 459
326 // This can happen if the child process is removed while the buffer is being 460 // This can happen if client is removed while the buffer is being allocated.
327 // allocated.
328 if (client_it == clients_.end()) { 461 if (client_it == clients_.end()) {
329 if (!handle.is_null()) { 462 if (!handle.is_null()) {
330 gpu_memory_buffer_factory_host_->DestroyGpuMemoryBuffer( 463 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id);
331 handle.id, child_client_id, 0); 464 if (host)
465 host->DestroyGpuMemoryBuffer(handle.id, client_id, 0);
332 } 466 }
333 callback.Run(gfx::GpuMemoryBufferHandle()); 467 callback.Run(gfx::GpuMemoryBufferHandle());
334 return; 468 return;
335 } 469 }
336 470
337 BufferMap& buffers = client_it->second; 471 BufferMap& buffers = client_it->second;
338 472
339 BufferMap::iterator buffer_it = buffers.find(id); 473 BufferMap::iterator buffer_it = buffers.find(id);
340 DCHECK(buffer_it != buffers.end()); 474 DCHECK(buffer_it != buffers.end());
341 DCHECK_EQ(buffer_it->second.type, gfx::EMPTY_BUFFER); 475 DCHECK_EQ(buffer_it->second.type, gfx::EMPTY_BUFFER);
342 476
343 // If the handle isn't valid, that means that the GPU process crashed or is 477 // If the handle isn't valid, that means that the GPU process crashed or is
344 // misbehaving so we remove the buffer entry and run the allocation callback 478 // misbehaving so we remove the buffer entry and run the allocation callback
345 // with an empty handle to indicate failure. 479 // with an empty handle to indicate failure.
346 bool valid_handle = !handle.is_null() && handle.id == id && 480 bool valid_handle = !handle.is_null() && handle.id == id;
347 handle.type != gfx::SHARED_MEMORY_BUFFER;
348 if (!valid_handle) { 481 if (!valid_handle) {
piman 2015/06/19 19:29:48 Do you need retry logic, like we do for the channe
reveman 2015/06/22 17:09:12 Good point. Added retry logic to latest patch. No
349 buffers.erase(buffer_it); 482 buffers.erase(buffer_it);
350 callback.Run(gfx::GpuMemoryBufferHandle()); 483 callback.Run(gfx::GpuMemoryBufferHandle());
351 return; 484 return;
352 } 485 }
353 486
354 // Store the type of this buffer so it can be cleaned up if the child 487 // Store the type and host id of this buffer so it can be cleaned up if the
355 // process is removed. 488 // client is removed.
356 buffer_it->second.type = handle.type; 489 buffer_it->second.type = handle.type;
490 buffer_it->second.gpu_host_id = gpu_host_id;
357 491
358 callback.Run(handle); 492 callback.Run(handle);
359 } 493 }
360 494
495 void BrowserGpuMemoryBufferManager::DestroyGpuMemoryBufferOnIO(
496 gfx::GpuMemoryBufferId id,
497 int client_id,
498 uint32 sync_point) {
499 DCHECK_CURRENTLY_ON(BrowserThread::IO);
500 DCHECK(clients_.find(client_id) != clients_.end());
501
502 BufferMap& buffers = clients_[client_id];
503
504 BufferMap::iterator buffer_it = buffers.find(id);
505 if (buffer_it == buffers.end()) {
506 LOG(ERROR) << "Invalid GpuMemoryBuffer ID for client.";
507 return;
508 }
509
510 // This can happen if a client managed to call this while a buffer is in the
511 // process of being allocated.
512 if (buffer_it->second.type == gfx::EMPTY_BUFFER) {
513 LOG(ERROR) << "Invalid GpuMemoryBuffer type.";
514 return;
515 }
516
517 GpuProcessHost* host = GpuProcessHost::FromID(buffer_it->second.gpu_host_id);
518 if (host)
519 host->DestroyGpuMemoryBuffer(id, client_id, sync_point);
520
521 buffers.erase(buffer_it);
522 }
523
361 } // namespace content 524 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698