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

Side by Side Diff: gpu/ipc/client/gpu_host_memory_buffer_manager.cc

Issue 2448983003: gpu: Refactor memory buffer handling code out of content.
Patch Set: . Created 4 years, 1 month 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "gpu/ipc/client/gpu_host_memory_buffer_manager.h"
6
7 #include "base/atomic_sequence_num.h"
8 #include "base/bind.h"
9 #include "base/synchronization/waitable_event.h"
10 #include "base/threading/thread_restrictions.h"
11 #include "base/threading/thread_task_runner_handle.h"
12 #include "base/trace_event/trace_event.h"
13 #include "gpu/ipc/client/gpu_memory_buffer_impl.h"
14 #include "gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.h"
15 #include "mojo/public/cpp/system/buffer.h"
16 #include "mojo/public/cpp/system/platform_handle.h"
17 #include "ui/gfx/buffer_format_util.h"
18
19 namespace {
20
21 base::StaticAtomicSequenceNumber g_next_generic_shared_memory_id;
22
23 gfx::GenericSharedMemoryId GetNextGenericSharedMemoryId() {
24 return gfx::GenericSharedMemoryId(g_next_generic_shared_memory_id.GetNext());
25 }
26
27 void GpuMemoryBufferDeleted(
28 scoped_refptr<base::SingleThreadTaskRunner> destruction_task_runner,
29 const gpu::GpuMemoryBufferImpl::DestructionCallback& destruction_callback,
30 const gpu::SyncToken& sync_token) {
31 destruction_task_runner->PostTask(
32 FROM_HERE, base::Bind(destruction_callback, sync_token));
33 }
34
35 } // namespace
36
37 namespace gpu {
38
39 ////////////////////////////////////////////////////////////////////////////////
40 // GpuHostMemoryBufferManager::CreateGpuMemoryBufferRequest
41
42 struct GpuHostMemoryBufferManager::CreateGpuMemoryBufferRequest {
43 CreateGpuMemoryBufferRequest(const gfx::Size& size,
44 gfx::BufferFormat format,
45 gfx::BufferUsage usage,
46 int client_id,
47 gpu::SurfaceHandle surface_handle)
48 : event(base::WaitableEvent::ResetPolicy::MANUAL,
49 base::WaitableEvent::InitialState::NOT_SIGNALED),
50 size(size),
51 format(format),
52 usage(usage),
53 client_id(client_id),
54 surface_handle(surface_handle) {}
55 ~CreateGpuMemoryBufferRequest() {}
56 base::WaitableEvent event;
57 gfx::Size size;
58 gfx::BufferFormat format;
59 gfx::BufferUsage usage;
60 int client_id;
61 gpu::SurfaceHandle surface_handle;
62 std::unique_ptr<gfx::GpuMemoryBuffer> result;
63 };
64
65 ////////////////////////////////////////////////////////////////////////////////
66 // GpuHostMemoryBufferManager::CreateGpuMemoryBufferFromHandleRequest
67
68 struct GpuHostMemoryBufferManager::CreateGpuMemoryBufferFromHandleRequest
69 : public CreateGpuMemoryBufferRequest {
70 CreateGpuMemoryBufferFromHandleRequest(
71 const gfx::GpuMemoryBufferHandle& handle,
72 const gfx::Size& size,
73 gfx::BufferFormat format,
74 int client_id)
75 : CreateGpuMemoryBufferRequest(size,
76 format,
77 gfx::BufferUsage::GPU_READ,
78 client_id,
79 gpu::kNullSurfaceHandle),
80 handle(handle) {}
81 ~CreateGpuMemoryBufferFromHandleRequest() {}
82 gfx::GpuMemoryBufferHandle handle;
83 };
84
85 ////////////////////////////////////////////////////////////////////////////////
86 // GpuHostMemoryBufferManager::BufferInfo
87
88 GpuHostMemoryBufferManager::BufferInfo::BufferInfo() = default;
89
90 GpuHostMemoryBufferManager::BufferInfo::BufferInfo(
91 const gfx::Size& size,
92 gfx::GpuMemoryBufferType type,
93 gfx::BufferFormat format,
94 gfx::BufferUsage usage,
95 int gpu_host_id)
96 : size(size),
97 type(type),
98 format(format),
99 usage(usage),
100 gpu_host_id(gpu_host_id) {}
101
102 GpuHostMemoryBufferManager::BufferInfo::BufferInfo(const BufferInfo& other) =
103 default;
104
105 GpuHostMemoryBufferManager::BufferInfo::~BufferInfo() {}
106
107 ////////////////////////////////////////////////////////////////////////////////
108 // GpuMemoryBufferManager
109
110 GpuHostMemoryBufferManager::GpuHostMemoryBufferManager() : gpu_client_id_(0) {}
111
112 GpuHostMemoryBufferManager::~GpuHostMemoryBufferManager() {}
113
114 void Run(const GpuHostMemoryBufferManager::AllocationCallback& callback,
115 gfx::GpuMemoryBufferHandle handle) {
116 callback.Run(handle);
117 }
118
119 void Proxy(scoped_refptr<base::SingleThreadTaskRunner> runner,
120 const GpuHostMemoryBufferManager::AllocationCallback& callback,
121 const gfx::GpuMemoryBufferHandle& handle) {
122 runner->PostTask(FROM_HERE, base::Bind(&Run, callback, handle));
123 }
124
125 gfx::GpuMemoryBufferHandle X(gfx::GpuMemoryBufferId id,
126 const gfx::Size& size,
127 gfx::BufferFormat format) {
128 size_t bytes = gfx::BufferSizeForBufferFormat(size, format);
129
130 mojo::ScopedSharedBufferHandle scoped_handle =
131 mojo::SharedBufferHandle::Create(bytes);
132 DCHECK(scoped_handle.is_valid());
133
134 base::SharedMemoryHandle platform_handle;
135 size_t shared_memory_size;
136 bool readonly;
137 MojoResult result = mojo::UnwrapSharedMemoryHandle(
138 std::move(scoped_handle), &platform_handle, &shared_memory_size, &readonly );
139 DCHECK_EQ(MOJO_RESULT_OK, result);
140 DCHECK_EQ(shared_memory_size, bytes);
141
142 gfx::GpuMemoryBufferHandle handle;
143 handle.type = gfx::SHARED_MEMORY_BUFFER;
144 handle.id = id;
145 handle.offset = 0;
146 handle.stride = static_cast<int32_t>(
147 gfx::RowSizeForBufferFormat(size.width(), format, 0));
148 handle.handle = platform_handle;
149 return handle;
150 }
151
152 void GpuHostMemoryBufferManager::AllocateGpuMemoryBufferForClient(
153 gfx::GpuMemoryBufferId id,
154 const gfx::Size& size,
155 gfx::BufferFormat format,
156 gfx::BufferUsage usage,
157 int child_client_id,
158 const AllocationCallback& callback) {
159 #if 0
160 DCHECK(io_task_runner_->BelongsToCurrentThread());
161 #else
162 if (!io_task_runner_->BelongsToCurrentThread()) {
163 io_task_runner_->PostTask(
164 FROM_HERE,
165 base::Bind(
166 &GpuHostMemoryBufferManager::AllocateGpuMemoryBufferForClient,
167 base::Unretained(this), id, size, format, usage, child_client_id,
168 base::Bind(&Proxy, base::ThreadTaskRunnerHandle::Get(), callback)));
169 return;
170 }
171 #endif
172
173 #if 0
174 // Use service side allocation for native configurations.
175 if (IsNativeGpuMemoryBufferConfiguration(format, usage)) {
176 CreateGpuMemoryBufferOnIO(
177 base::Bind(&HostCreateGpuMemoryBuffer, gpu::kNullSurfaceHandle), id,
178 size, format, usage, child_client_id, false, callback);
179 return;
180 }
181 #endif
182
183 // Early out if we cannot fallback to shared memory buffer.
184 if (!gpu::GpuMemoryBufferImplSharedMemory::IsUsageSupported(usage) ||
185 !gpu::GpuMemoryBufferImplSharedMemory::IsSizeValidForFormat(size,
186 format)) {
187 callback.Run(gfx::GpuMemoryBufferHandle());
188 return;
189 }
190
191 BufferMap& buffers = clients_[child_client_id];
192
193 // Allocate shared memory buffer as fallback.
194 auto insert_result = buffers.insert(std::make_pair(
195 id, BufferInfo(size, gfx::SHARED_MEMORY_BUFFER, format, usage, 0)));
196 if (!insert_result.second) {
197 DLOG(ERROR) << "Child process attempted to allocate a GpuMemoryBuffer with "
198 "an existing ID.";
199 callback.Run(gfx::GpuMemoryBufferHandle());
200 return;
201 }
202
203 // TODO(sad): We need a valid ProcessHandle, but it is required only on win32.
204 base::ProcessHandle child_process_handle = base::kNullProcessHandle;
205 callback.Run(gpu::GpuMemoryBufferImplSharedMemory::AllocateForChildProcess(
206 id, size, format, child_process_handle));
207 }
208
209 void GpuHostMemoryBufferManager::HandleCreateGpuMemoryBufferOnIO(
210 CreateGpuMemoryBufferRequest* request) {
211 DCHECK(io_task_runner_->BelongsToCurrentThread());
212
213 gfx::GpuMemoryBufferId new_id = GetNextGenericSharedMemoryId();
214
215 #if 0
216 // Use service side allocation for native configurations.
217 if (IsNativeGpuMemoryBufferConfiguration(request->format, request->usage)) {
218 // Note: Unretained is safe as this is only used for synchronous allocation
219 // from a non-IO thread.
220 CreateGpuMemoryBufferOnIO(
221 base::Bind(&HostCreateGpuMemoryBuffer, request->surface_handle), new_id,
222 request->size, request->format, request->usage, request->client_id,
223 false,
224 base::Bind(
225 &GpuHostMemoryBufferManager::HandleGpuMemoryBufferCreatedOnIO,
226 base::Unretained(this), base::Unretained(request)));
227 return;
228 }
229 #endif
230
231 DCHECK(GpuMemoryBufferImplSharedMemory::IsUsageSupported(request->usage))
232 << static_cast<int>(request->usage);
233
234 BufferMap& buffers = clients_[request->client_id];
235
236 // Allocate shared memory buffer as fallback.
237 auto insert_result = buffers.insert(std::make_pair(
238 new_id, BufferInfo(request->size, gfx::SHARED_MEMORY_BUFFER,
239 request->format, request->usage, 0)));
240 DCHECK(insert_result.second);
241
242 // Note: Unretained is safe as IO thread is stopped before manager is
243 // destroyed.
244 request->result = GpuMemoryBufferImplSharedMemory::Create(
245 new_id, request->size, request->format,
246 base::Bind(
247 &GpuMemoryBufferDeleted, io_task_runner_,
248 base::Bind(&GpuHostMemoryBufferManager::DestroyGpuMemoryBufferOnIO,
249 base::Unretained(this), new_id, request->client_id)));
250 request->event.Signal();
251 }
252
253 void GpuHostMemoryBufferManager::HandleCreateGpuMemoryBufferFromHandleOnIO(
254 CreateGpuMemoryBufferFromHandleRequest* request) {
255 DCHECK(io_task_runner_->BelongsToCurrentThread());
256
257 gfx::GpuMemoryBufferId new_id = GetNextGenericSharedMemoryId();
258
259 BufferMap& buffers = clients_[request->client_id];
260 auto insert_result = buffers.insert(
261 std::make_pair(new_id, BufferInfo(request->size, request->handle.type,
262 request->format, request->usage, 0)));
263 DCHECK(insert_result.second);
264
265 gfx::GpuMemoryBufferHandle handle = request->handle;
266 handle.id = new_id;
267
268 // Note: Unretained is safe as IO thread is stopped before manager is
269 // destroyed.
270 request->result = GpuMemoryBufferImpl::CreateFromHandle(
271 handle, request->size, request->format, request->usage,
272 base::Bind(
273 &GpuMemoryBufferDeleted, io_task_runner_,
274 base::Bind(&GpuHostMemoryBufferManager::DestroyGpuMemoryBufferOnIO,
275 base::Unretained(this), new_id, request->client_id)));
276 request->event.Signal();
277 }
278
279 void GpuHostMemoryBufferManager::DestroyGpuMemoryBufferOnIO(
280 gfx::GpuMemoryBufferId id,
281 int client_id,
282 const gpu::SyncToken& sync_token) {
283 DCHECK(io_task_runner_->BelongsToCurrentThread());
284 DCHECK(clients_.find(client_id) != clients_.end());
285
286 BufferMap& buffers = clients_[client_id];
287
288 BufferMap::iterator buffer_it = buffers.find(id);
289 if (buffer_it == buffers.end()) {
290 LOG(ERROR) << "Invalid GpuMemoryBuffer ID for client.";
291 return;
292 }
293
294 // This can happen if a client managed to call this while a buffer is in the
295 // process of being allocated.
296 if (buffer_it->second.type == gfx::EMPTY_BUFFER) {
297 LOG(ERROR) << "Invalid GpuMemoryBuffer type.";
298 return;
299 }
300
301 #if 0
302 GpuProcessHost* host = GpuProcessHost::FromID(buffer_it->second.gpu_host_id);
303 if (host)
304 host->DestroyGpuMemoryBuffer(id, client_id, sync_token);
305 #endif
306
307 buffers.erase(buffer_it);
308 }
309
310 std::unique_ptr<gfx::GpuMemoryBuffer>
311 GpuHostMemoryBufferManager::AllocateGpuMemoryBuffer(
312 const gfx::Size& size,
313 gfx::BufferFormat format,
314 gfx::BufferUsage usage,
315 SurfaceHandle surface_handle) {
316 DCHECK(!io_task_runner_->BelongsToCurrentThread());
317
318 CreateGpuMemoryBufferRequest request(size, format, usage, gpu_client_id_,
319 surface_handle);
320 io_task_runner_->PostTask(
321 FROM_HERE,
322 base::Bind(&GpuHostMemoryBufferManager::HandleCreateGpuMemoryBufferOnIO,
323 base::Unretained(this), // Safe as we wait for result below.
324 base::Unretained(&request)));
325 TRACE_EVENT0("browser",
326 "GpuHostMemoryBufferManager::AllocateGpuMemoryBufferForSurface");
327 base::ThreadRestrictions::ScopedAllowWait allow_wait;
328 request.event.Wait();
329 return std::move(request.result);
330 }
331
332 std::unique_ptr<gfx::GpuMemoryBuffer>
333 GpuHostMemoryBufferManager::CreateGpuMemoryBufferFromHandle(
334 const gfx::GpuMemoryBufferHandle& handle,
335 const gfx::Size& size,
336 gfx::BufferFormat format) {
337 DCHECK(!io_task_runner_->BelongsToCurrentThread());
338
339 CreateGpuMemoryBufferFromHandleRequest request(handle, size, format,
340 gpu_client_id_);
341 io_task_runner_->PostTask(
342 FROM_HERE,
343 base::Bind(&GpuHostMemoryBufferManager::
344 HandleCreateGpuMemoryBufferFromHandleOnIO,
345 base::Unretained(this), // Safe as we wait for result below.
346 base::Unretained(&request)));
347
348 // We're blocking the UI thread, which is generally undesirable.
349 TRACE_EVENT0(
350 "browser",
351 "GpuHostMemoryBufferManager::CreateGpuMemoryBufferFromHandle");
352 base::ThreadRestrictions::ScopedAllowWait allow_wait;
353 request.event.Wait();
354 return std::move(request.result);
355 }
356
357 gfx::GpuMemoryBuffer*
358 GpuHostMemoryBufferManager::GpuMemoryBufferFromClientBuffer(
359 ClientBuffer buffer) {
360 return gpu::GpuMemoryBufferImpl::FromClientBuffer(buffer);
361 }
362
363 void GpuHostMemoryBufferManager::SetDestructionSyncToken(
364 gfx::GpuMemoryBuffer* buffer,
365 const SyncToken& sync_token) {}
366
367 } // namespace gpu
OLDNEW
« no previous file with comments | « gpu/ipc/client/gpu_host_memory_buffer_manager.h ('k') | gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698