blob: 2fb56420c442e2f7c571d600dc66083358e280a6 [file] [log] [blame]
Weiliang Chen7cf2b5322020-01-23 02:04:171// Copyright 2019 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/shared_image_interface_in_process.h"
6
7#include "base/bind.h"
8#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
9#include "gpu/command_buffer/common/sync_token.h"
10#include "gpu/command_buffer/service/mailbox_manager.h"
11#include "gpu/command_buffer/service/shared_image_factory.h"
12#include "gpu/command_buffer/service/sync_point_manager.h"
13#include "gpu/ipc/command_buffer_task_executor.h"
14#include "gpu/ipc/common/gpu_client_ids.h"
15#include "gpu/ipc/single_task_sequence.h"
16#include "ui/gl/gl_context.h"
17
18namespace gpu {
19SharedImageInterfaceInProcess::SharedImageInterfaceInProcess(
20 CommandBufferTaskExecutor* task_executor,
21 SingleTaskSequence* single_task_sequence,
22 CommandBufferId command_buffer_id,
23 MailboxManager* mailbox_manager,
24 ImageFactory* image_factory,
25 MemoryTracker* memory_tracker,
26 std::unique_ptr<CommandBufferHelper> command_buffer_helper)
27 : task_sequence_(single_task_sequence),
28 command_buffer_id_(command_buffer_id),
29 command_buffer_helper_(std::move(command_buffer_helper)),
30 shared_image_manager_(task_executor->shared_image_manager()),
31 mailbox_manager_(mailbox_manager),
32 sync_point_manager_(task_executor->sync_point_manager()) {
33 DETACH_FROM_SEQUENCE(gpu_sequence_checker_);
34 task_sequence_->ScheduleTask(
35 base::BindOnce(&SharedImageInterfaceInProcess::SetUpOnGpu,
36 base::Unretained(this), task_executor, image_factory,
37 memory_tracker),
38 {});
39}
40
41SharedImageInterfaceInProcess::~SharedImageInterfaceInProcess() {
42 base::WaitableEvent completion(
43 base::WaitableEvent::ResetPolicy::MANUAL,
44 base::WaitableEvent::InitialState::NOT_SIGNALED);
45
46 task_sequence_->ScheduleTask(
47 base::BindOnce(&SharedImageInterfaceInProcess::DestroyOnGpu,
48 base::Unretained(this), &completion),
49 {});
50 completion.Wait();
51}
52
53void SharedImageInterfaceInProcess::SetUpOnGpu(
54 CommandBufferTaskExecutor* task_executor,
55 ImageFactory* image_factory,
56 MemoryTracker* memory_tracker) {
57 DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_);
58
59 context_state_ = task_executor->GetSharedContextState().get();
60 create_factory_ = base::BindOnce(
61 [](CommandBufferTaskExecutor* task_executor, ImageFactory* image_factory,
62 MemoryTracker* memory_tracker, MailboxManager* mailbox_manager,
63 bool enable_wrapped_sk_image) {
64 auto shared_image_factory = std::make_unique<SharedImageFactory>(
65 task_executor->gpu_preferences(),
66 GpuDriverBugWorkarounds(task_executor->gpu_feature_info()
67 .enabled_gpu_driver_bug_workarounds),
68 task_executor->gpu_feature_info(),
69 task_executor->GetSharedContextState().get(), mailbox_manager,
70 task_executor->shared_image_manager(), image_factory,
71 memory_tracker, enable_wrapped_sk_image);
72 return shared_image_factory;
73 },
74 task_executor, image_factory, memory_tracker, mailbox_manager_);
75
76 // Make the SharedImageInterface use the same sequence as the command buffer,
77 // it's necessary for WebView because of the blocking behavior.
78 // TODO(piman): see if it's worth using a different sequence for non-WebView.
79 sync_point_client_state_ = sync_point_manager_->CreateSyncPointClientState(
80 CommandBufferNamespace::IN_PROCESS, command_buffer_id_,
81 task_sequence_->GetSequenceId());
82}
83
84void SharedImageInterfaceInProcess::DestroyOnGpu(
85 base::WaitableEvent* completion) {
86 bool have_context = MakeContextCurrent();
87 if (shared_image_factory_)
88 shared_image_factory_->DestroyAllSharedImages(have_context);
89
90 if (sync_point_client_state_) {
91 sync_point_client_state_->Destroy();
92 sync_point_client_state_ = nullptr;
93 }
94 completion->Signal();
95}
96
Peng Huangca587f992020-06-05 17:19:2897bool SharedImageInterfaceInProcess::MakeContextCurrent(bool needs_gl) {
Weiliang Chen7cf2b5322020-01-23 02:04:1798 if (!context_state_)
99 return false;
100
101 if (context_state_->context_lost())
102 return false;
103
104 // |shared_image_factory_| never writes to the surface, so skip unnecessary
105 // MakeCurrent to improve performance. https://crbug.com/457431
106 auto* context = context_state_->real_context();
Jonathan Backerbaf79d92020-06-01 21:30:30107 if (context->IsCurrent(nullptr))
Peng Huangca587f992020-06-05 17:19:28108 return !context_state_->CheckResetStatus(needs_gl);
109 return context_state_->MakeCurrent(/*surface=*/nullptr, needs_gl);
Weiliang Chen7cf2b5322020-01-23 02:04:17110}
111
112void SharedImageInterfaceInProcess::LazyCreateSharedImageFactory() {
113 // This function is always called right after we call MakeContextCurrent().
114 if (shared_image_factory_)
115 return;
116
Peng Huangca587f992020-06-05 17:19:28117 // Some shared image backing factories will use GL in ctor, so we need GL even
118 // if chrome is using non-GL backing.
119 if (!MakeContextCurrent(/*needs_gl=*/true))
120 return;
121
Weiliang Chen7cf2b5322020-01-23 02:04:17122 // We need WrappedSkImage to support creating a SharedImage with pixel data
123 // when GL is unavailable. This is used in various unit tests.
124 const bool enable_wrapped_sk_image =
125 command_buffer_helper_ && command_buffer_helper_->EnableWrappedSkImage();
126 shared_image_factory_ =
127 std::move(create_factory_).Run(enable_wrapped_sk_image);
128}
129
130Mailbox SharedImageInterfaceInProcess::CreateSharedImage(
131 viz::ResourceFormat format,
132 const gfx::Size& size,
133 const gfx::ColorSpace& color_space,
Nathan Zabriskie659c2742020-07-16 03:49:32134 GrSurfaceOrigin surface_origin,
135 SkAlphaType alpha_type,
Paulo Warrenfad0b112020-03-03 21:40:26136 uint32_t usage,
137 gpu::SurfaceHandle surface_handle) {
Weiliang Chen7cf2b5322020-01-23 02:04:17138 auto mailbox = Mailbox::GenerateForSharedImage();
139 {
140 base::AutoLock lock(lock_);
141 // Note: we enqueue the task under the lock to guarantee monotonicity of
142 // the release ids as seen by the service. Unretained is safe because
143 // SharedImageInterfaceInProcess synchronizes with the GPU thread at
144 // destruction time, cancelling tasks, before |this| is destroyed.
145 ScheduleGpuTask(
146 base::BindOnce(
147 &SharedImageInterfaceInProcess::CreateSharedImageOnGpuThread,
Paulo Warrenfad0b112020-03-03 21:40:26148 base::Unretained(this), mailbox, format, surface_handle, size,
Nathan Zabriskie659c2742020-07-16 03:49:32149 color_space, surface_origin, alpha_type, usage,
150 MakeSyncToken(next_fence_sync_release_++)),
Weiliang Chen7cf2b5322020-01-23 02:04:17151 {});
152 }
153 return mailbox;
154}
155
156void SharedImageInterfaceInProcess::CreateSharedImageOnGpuThread(
157 const Mailbox& mailbox,
158 viz::ResourceFormat format,
Paulo Warrenfad0b112020-03-03 21:40:26159 gpu::SurfaceHandle surface_handle,
Weiliang Chen7cf2b5322020-01-23 02:04:17160 const gfx::Size& size,
161 const gfx::ColorSpace& color_space,
Nathan Zabriskie659c2742020-07-16 03:49:32162 GrSurfaceOrigin surface_origin,
163 SkAlphaType alpha_type,
Weiliang Chen7cf2b5322020-01-23 02:04:17164 uint32_t usage,
165 const SyncToken& sync_token) {
166 DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_);
167 if (!MakeContextCurrent())
168 return;
169
170 LazyCreateSharedImageFactory();
171
Paulo Warrenfad0b112020-03-03 21:40:26172 if (!shared_image_factory_->CreateSharedImage(
Nathan Zabriskieeed7e6c2020-07-18 01:34:42173 mailbox, format, size, color_space, surface_origin, alpha_type,
174 surface_handle, usage)) {
Weiliang Chen7cf2b5322020-01-23 02:04:17175 // Signal errors by losing the command buffer.
176 command_buffer_helper_->SetError();
177 return;
178 }
179 mailbox_manager_->PushTextureUpdates(sync_token);
180 sync_point_client_state_->ReleaseFenceSync(sync_token.release_count());
181}
182
183Mailbox SharedImageInterfaceInProcess::CreateSharedImage(
184 viz::ResourceFormat format,
185 const gfx::Size& size,
186 const gfx::ColorSpace& color_space,
Nathan Zabriskie659c2742020-07-16 03:49:32187 GrSurfaceOrigin surface_origin,
188 SkAlphaType alpha_type,
Weiliang Chen7cf2b5322020-01-23 02:04:17189 uint32_t usage,
190 base::span<const uint8_t> pixel_data) {
191 auto mailbox = Mailbox::GenerateForSharedImage();
192 std::vector<uint8_t> pixel_data_copy(pixel_data.begin(), pixel_data.end());
193 {
194 base::AutoLock lock(lock_);
195 // Note: we enqueue the task under the lock to guarantee monotonicity of
196 // the release ids as seen by the service. Unretained is safe because
197 // InProcessCommandBuffer synchronizes with the GPU thread at destruction
198 // time, cancelling tasks, before |this| is destroyed.
Nathan Zabriskie659c2742020-07-16 03:49:32199 ScheduleGpuTask(
200 base::BindOnce(&SharedImageInterfaceInProcess::
201 CreateSharedImageWithDataOnGpuThread,
202 base::Unretained(this), mailbox, format, size,
203 color_space, surface_origin, alpha_type, usage,
204 MakeSyncToken(next_fence_sync_release_++),
205 std::move(pixel_data_copy)),
206 {});
Weiliang Chen7cf2b5322020-01-23 02:04:17207 }
208 return mailbox;
209}
210
211void SharedImageInterfaceInProcess::CreateSharedImageWithDataOnGpuThread(
212 const Mailbox& mailbox,
213 viz::ResourceFormat format,
214 const gfx::Size& size,
215 const gfx::ColorSpace& color_space,
Nathan Zabriskie659c2742020-07-16 03:49:32216 GrSurfaceOrigin surface_origin,
217 SkAlphaType alpha_type,
Weiliang Chen7cf2b5322020-01-23 02:04:17218 uint32_t usage,
219 const SyncToken& sync_token,
220 std::vector<uint8_t> pixel_data) {
221 DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_);
222 if (!MakeContextCurrent())
223 return;
224
225 LazyCreateSharedImageFactory();
226
227 if (!shared_image_factory_->CreateSharedImage(
Nathan Zabriskieeed7e6c2020-07-18 01:34:42228 mailbox, format, size, color_space, surface_origin, alpha_type, usage,
229 pixel_data)) {
Weiliang Chen7cf2b5322020-01-23 02:04:17230 // Signal errors by losing the command buffer.
231 command_buffer_helper_->SetError();
232 return;
233 }
234 mailbox_manager_->PushTextureUpdates(sync_token);
235 sync_point_client_state_->ReleaseFenceSync(sync_token.release_count());
236}
237
238Mailbox SharedImageInterfaceInProcess::CreateSharedImage(
239 gfx::GpuMemoryBuffer* gpu_memory_buffer,
240 GpuMemoryBufferManager* gpu_memory_buffer_manager,
241 const gfx::ColorSpace& color_space,
Nathan Zabriskie659c2742020-07-16 03:49:32242 GrSurfaceOrigin surface_origin,
243 SkAlphaType alpha_type,
Weiliang Chen7cf2b5322020-01-23 02:04:17244 uint32_t usage) {
245 DCHECK(gpu_memory_buffer->GetType() == gfx::NATIVE_PIXMAP ||
246 gpu_memory_buffer->GetType() == gfx::ANDROID_HARDWARE_BUFFER ||
247 gpu_memory_buffer_manager);
248
249 // TODO(piman): DCHECK GMB format support.
250 DCHECK(IsImageSizeValidForGpuMemoryBufferFormat(
251 gpu_memory_buffer->GetSize(), gpu_memory_buffer->GetFormat()));
252
253 auto mailbox = Mailbox::GenerateForSharedImage();
254 gfx::GpuMemoryBufferHandle handle = gpu_memory_buffer->CloneHandle();
255 bool requires_sync_token = handle.type == gfx::IO_SURFACE_BUFFER;
256 SyncToken sync_token;
257 {
258 base::AutoLock lock(lock_);
259 sync_token = MakeSyncToken(next_fence_sync_release_++);
260 // Note: we enqueue the task under the lock to guarantee monotonicity of
261 // the release ids as seen by the service. Unretained is safe because
262 // InProcessCommandBuffer synchronizes with the GPU thread at destruction
263 // time, cancelling tasks, before |this| is destroyed.
264 ScheduleGpuTask(
265 base::BindOnce(
266 &SharedImageInterfaceInProcess::CreateGMBSharedImageOnGpuThread,
267 base::Unretained(this), mailbox, std::move(handle),
268 gpu_memory_buffer->GetFormat(), gpu_memory_buffer->GetSize(),
Nathan Zabriskie659c2742020-07-16 03:49:32269 color_space, surface_origin, alpha_type, usage, sync_token),
Weiliang Chen7cf2b5322020-01-23 02:04:17270 {});
271 }
272 if (requires_sync_token) {
273 sync_token.SetVerifyFlush();
274 gpu_memory_buffer_manager->SetDestructionSyncToken(gpu_memory_buffer,
275 sync_token);
276 }
277 return mailbox;
278}
279
280void SharedImageInterfaceInProcess::CreateGMBSharedImageOnGpuThread(
281 const Mailbox& mailbox,
282 gfx::GpuMemoryBufferHandle handle,
283 gfx::BufferFormat format,
284 const gfx::Size& size,
285 const gfx::ColorSpace& color_space,
Nathan Zabriskie659c2742020-07-16 03:49:32286 GrSurfaceOrigin surface_origin,
287 SkAlphaType alpha_type,
Weiliang Chen7cf2b5322020-01-23 02:04:17288 uint32_t usage,
289 const SyncToken& sync_token) {
290 DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_);
291 if (!MakeContextCurrent())
292 return;
293
294 LazyCreateSharedImageFactory();
295
296 // TODO(piman): add support for SurfaceHandle (for backbuffers for ozone/drm).
297 SurfaceHandle surface_handle = kNullSurfaceHandle;
298 if (!shared_image_factory_->CreateSharedImage(
299 mailbox, kInProcessCommandBufferClientId, std::move(handle), format,
Nathan Zabriskieeed7e6c2020-07-18 01:34:42300 surface_handle, size, color_space, surface_origin, alpha_type,
301 usage)) {
Weiliang Chen7cf2b5322020-01-23 02:04:17302 // Signal errors by losing the command buffer.
303 // Signal errors by losing the command buffer.
304 command_buffer_helper_->SetError();
305 return;
306 }
307 mailbox_manager_->PushTextureUpdates(sync_token);
308 sync_point_client_state_->ReleaseFenceSync(sync_token.release_count());
309}
310
311SharedImageInterface::SwapChainMailboxes
312SharedImageInterfaceInProcess::CreateSwapChain(
313 viz::ResourceFormat format,
314 const gfx::Size& size,
315 const gfx::ColorSpace& color_space,
Nathan Zabriskie659c2742020-07-16 03:49:32316 GrSurfaceOrigin surface_origin,
317 SkAlphaType alpha_type,
Weiliang Chen7cf2b5322020-01-23 02:04:17318 uint32_t usage) {
319 NOTREACHED();
320 return {};
321}
322
323void SharedImageInterfaceInProcess::PresentSwapChain(
324 const SyncToken& sync_token,
325 const Mailbox& mailbox) {
326 NOTREACHED();
327}
328
329#if defined(OS_FUCHSIA)
330void SharedImageInterfaceInProcess::RegisterSysmemBufferCollection(
331 gfx::SysmemBufferCollectionId id,
Sergey Ulanov28068562020-06-09 23:28:07332 zx::channel token,
333 gfx::BufferFormat format,
334 gfx::BufferUsage usage) {
Weiliang Chen7cf2b5322020-01-23 02:04:17335 NOTREACHED();
336}
337void SharedImageInterfaceInProcess::ReleaseSysmemBufferCollection(
338 gfx::SysmemBufferCollectionId id) {
339 NOTREACHED();
340}
341#endif // defined(OS_FUCHSIA)
342
343void SharedImageInterfaceInProcess::UpdateSharedImage(
344 const SyncToken& sync_token,
345 const Mailbox& mailbox) {
346 UpdateSharedImage(sync_token, nullptr, mailbox);
347}
348
349void SharedImageInterfaceInProcess::UpdateSharedImage(
350 const SyncToken& sync_token,
351 std::unique_ptr<gfx::GpuFence> acquire_fence,
352 const Mailbox& mailbox) {
353 DCHECK(!acquire_fence);
354 base::AutoLock lock(lock_);
355 // Note: we enqueue the task under the lock to guarantee monotonicity of
356 // the release ids as seen by the service. Unretained is safe because
357 // InProcessCommandBuffer synchronizes with the GPU thread at destruction
358 // time, cancelling tasks, before |this| is destroyed.
359 ScheduleGpuTask(
360 base::BindOnce(
361 &SharedImageInterfaceInProcess::UpdateSharedImageOnGpuThread,
362 base::Unretained(this), mailbox,
363 MakeSyncToken(next_fence_sync_release_++)),
364 {sync_token});
365}
366
367void SharedImageInterfaceInProcess::UpdateSharedImageOnGpuThread(
368 const Mailbox& mailbox,
369 const SyncToken& sync_token) {
370 DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_);
371 if (!MakeContextCurrent())
372 return;
373
374 if (!shared_image_factory_ ||
375 !shared_image_factory_->UpdateSharedImage(mailbox)) {
376 // Signal errors by losing the command buffer.
377 command_buffer_helper_->SetError();
378 return;
379 }
380 mailbox_manager_->PushTextureUpdates(sync_token);
381 sync_point_client_state_->ReleaseFenceSync(sync_token.release_count());
382}
383
384void SharedImageInterfaceInProcess::DestroySharedImage(
385 const SyncToken& sync_token,
386 const Mailbox& mailbox) {
387 // Use sync token dependency to ensure that the destroy task does not run
388 // before sync token is released.
389 ScheduleGpuTask(
390 base::BindOnce(
391 &SharedImageInterfaceInProcess::DestroySharedImageOnGpuThread,
392 base::Unretained(this), mailbox),
393 {sync_token});
394}
395
396void SharedImageInterfaceInProcess::DestroySharedImageOnGpuThread(
397 const Mailbox& mailbox) {
398 DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_);
399 if (!MakeContextCurrent())
400 return;
401
402 if (!shared_image_factory_ ||
403 !shared_image_factory_->DestroySharedImage(mailbox)) {
404 // Signal errors by losing the command buffer.
405 command_buffer_helper_->SetError();
406 }
407}
408
Vikas Soni08dfc582020-06-09 21:29:57409void SharedImageInterfaceInProcess::WaitSyncTokenOnGpuThread(
410 const SyncToken& sync_token) {
411 DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_);
412 if (!MakeContextCurrent())
413 return;
414
415 mailbox_manager_->PushTextureUpdates(sync_token);
416 sync_point_client_state_->ReleaseFenceSync(sync_token.release_count());
417}
418
Weiliang Chen7cf2b5322020-01-23 02:04:17419SyncToken SharedImageInterfaceInProcess::GenUnverifiedSyncToken() {
420 base::AutoLock lock(lock_);
421 return MakeSyncToken(next_fence_sync_release_ - 1);
422}
423
424SyncToken SharedImageInterfaceInProcess::GenVerifiedSyncToken() {
425 base::AutoLock lock(lock_);
426 SyncToken sync_token = MakeSyncToken(next_fence_sync_release_ - 1);
427 sync_token.SetVerifyFlush();
428 return sync_token;
429}
430
Vikas Soni08dfc582020-06-09 21:29:57431void SharedImageInterfaceInProcess::WaitSyncToken(const SyncToken& sync_token) {
432 base::AutoLock lock(lock_);
433
434 ScheduleGpuTask(
435 base::BindOnce(&SharedImageInterfaceInProcess::WaitSyncTokenOnGpuThread,
436 base::Unretained(this),
437 MakeSyncToken(next_fence_sync_release_++)),
438 {sync_token});
439}
440
Weiliang Chen7cf2b5322020-01-23 02:04:17441void SharedImageInterfaceInProcess::Flush() {
442 // No need to flush in this implementation.
443}
444
445scoped_refptr<gfx::NativePixmap> SharedImageInterfaceInProcess::GetNativePixmap(
446 const gpu::Mailbox& mailbox) {
447 DCHECK(shared_image_manager_->is_thread_safe());
448 return shared_image_manager_->GetNativePixmap(mailbox);
449}
450
451void SharedImageInterfaceInProcess::WrapTaskWithGpuUrl(base::OnceClosure task) {
452 if (command_buffer_helper_) {
453 command_buffer_helper_->WrapTaskWithGpuCheck(std::move(task));
454 } else {
455 std::move(task).Run();
456 }
457}
458
459void SharedImageInterfaceInProcess::ScheduleGpuTask(
460 base::OnceClosure task,
461 std::vector<SyncToken> sync_token_fences) {
462 base::OnceClosure gpu_task =
463 base::BindOnce(&SharedImageInterfaceInProcess::WrapTaskWithGpuUrl,
464 base::Unretained(this), std::move(task));
465
466 task_sequence_->ScheduleTask(std::move(gpu_task),
467 std::move(sync_token_fences));
468}
469
470} // namespace gpu