blob: be0d4715ce83f6ee87fde137fdd44b141404639d [file] [log] [blame]
[email protected]92dd77772013-08-01 23:57:561// Copyright 2013 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
fsamuel600b99e2016-11-11 07:50:265#include "gpu/ipc/in_process_command_buffer.h"
[email protected]92dd77772013-08-01 23:57:566
avif15d60a2015-12-21 17:06:337#include <stddef.h>
8#include <stdint.h>
9
[email protected]efaff842014-02-25 18:13:2710#include <set>
[email protected]92dd77772013-08-01 23:57:5611#include <utility>
12
kylechar8eebde302017-08-22 21:50:3913#include "base/atomic_sequence_num.h"
[email protected]92dd77772013-08-01 23:57:5614#include "base/bind.h"
15#include "base/bind_helpers.h"
Jonathan Backerbd345c1f2018-02-14 21:44:2316#include "base/callback_helpers.h"
boliua9987672015-08-26 22:51:2117#include "base/command_line.h"
Brett Wilsona62d9c02017-09-20 20:53:2018#include "base/containers/queue.h"
[email protected]92dd77772013-08-01 23:57:5619#include "base/lazy_instance.h"
skyostil0ad2c542015-05-07 11:52:0120#include "base/location.h"
[email protected]92dd77772013-08-01 23:57:5621#include "base/logging.h"
22#include "base/memory/weak_ptr.h"
reveman730fd9612015-11-11 01:22:4323#include "base/numerics/safe_conversions.h"
[email protected]61724842013-08-07 09:46:0924#include "base/sequence_checker.h"
skyostil0ad2c542015-05-07 11:52:0125#include "base/single_thread_task_runner.h"
kylechar2fdaa042018-07-03 17:36:2326#include "base/threading/thread.h"
gabb23705312016-05-11 18:44:5627#include "base/threading/thread_task_runner_handle.h"
Kevin Marshall03cda642017-08-16 22:27:0528#include "build/build_config.h"
danakj10057772016-04-12 19:35:4429#include "gpu/command_buffer/client/gpu_control_client.h"
reveman2232bce2014-10-29 01:28:0530#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
penghuangcfa7cae2016-04-06 21:11:5031#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
Christopher Cameron4bc282bb2017-12-03 11:24:0532#include "gpu/command_buffer/common/swap_buffers_complete_params.h"
Eric Karlb6b2c632018-05-07 22:45:0433#include "gpu/command_buffer/common/swap_buffers_flags.h"
dyen1e5cd822015-10-12 18:07:0934#include "gpu/command_buffer/common/sync_token.h"
[email protected]92dd77772013-08-01 23:57:5635#include "gpu/command_buffer/service/command_buffer_service.h"
36#include "gpu/command_buffer/service/context_group.h"
37#include "gpu/command_buffer/service/gl_context_virtual.h"
kylechar22b56412018-04-13 15:58:2138#include "gpu/command_buffer/service/gl_state_restorer_impl.h"
Jonathan Backer0cd1c4322018-04-17 16:57:1039#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
Klaus Weidnere66cc7d2017-12-09 17:26:3040#include "gpu/command_buffer/service/gpu_fence_manager.h"
Chandan Padhi07f05c02017-09-19 02:52:5341#include "gpu/command_buffer/service/gpu_tracer.h"
reveman2232bce2014-10-29 01:28:0542#include "gpu/command_buffer/service/image_factory.h"
Antoine Labour40b0ca42018-01-03 20:15:3443#include "gpu/command_buffer/service/mailbox_manager_factory.h"
boliua9987672015-08-26 22:51:2144#include "gpu/command_buffer/service/memory_program_cache.h"
dcheng6ef3c5552014-08-30 05:34:1945#include "gpu/command_buffer/service/memory_tracking.h"
[email protected]b63f1d62014-07-18 15:40:5946#include "gpu/command_buffer/service/query_manager.h"
Jonathan Backer0cd1c4322018-04-17 16:57:1047#include "gpu/command_buffer/service/raster_decoder.h"
Khushaldb2d4ad72018-07-03 22:36:2748#include "gpu/command_buffer/service/raster_decoder_context_state.h"
geofflangdf7fff2d42016-11-11 00:34:0349#include "gpu/command_buffer/service/service_utils.h"
boliu0aa0158b2015-02-11 04:06:0150#include "gpu/command_buffer/service/sync_point_manager.h"
[email protected]92dd77772013-08-01 23:57:5651#include "gpu/command_buffer/service/transfer_buffer_manager.h"
Sunny Sachanandani93c2ec12017-06-30 03:26:4552#include "gpu/config/gpu_crash_keys.h"
ericrk41a1579e2017-02-10 20:56:2853#include "gpu/config/gpu_feature_info.h"
Jonathan Backer0af509962018-05-30 16:05:0754#include "gpu/config/gpu_preferences.h"
Jonathan Backereba6af42018-05-03 22:47:4355#include "gpu/config/gpu_switches.h"
kylechar2fdaa042018-07-03 17:36:2356#include "gpu/ipc/command_buffer_task_executor.h"
fsamueledc0c2c2016-11-18 22:28:0457#include "gpu/ipc/gpu_in_process_thread_service.h"
Jonathan Backer76dfd502018-05-03 18:34:3158#include "gpu/ipc/host/gpu_memory_buffer_support.h"
kylechar8e7c5e4d2017-12-04 23:43:1759#include "gpu/ipc/service/gpu_channel_manager_delegate.h"
fsamueledc0c2c2016-11-18 22:28:0460#include "gpu/ipc/service/image_transport_surface.h"
tfarinaebe974f02015-01-03 04:25:3261#include "ui/gfx/geometry/size.h"
Klaus Weidnere66cc7d2017-12-09 17:26:3062#include "ui/gfx/gpu_fence.h"
63#include "ui/gfx/gpu_fence_handle.h"
[email protected]92dd77772013-08-01 23:57:5664#include "ui/gl/gl_context.h"
65#include "ui/gl/gl_image.h"
reveman5f717f82015-05-21 23:21:0766#include "ui/gl/gl_image_shared_memory.h"
[email protected]92dd77772013-08-01 23:57:5667#include "ui/gl/gl_share_group.h"
Khushaldb2d4ad72018-07-03 22:36:2768#include "ui/gl/gl_version_info.h"
69#include "ui/gl/init/create_gr_gl_interface.h"
kylechar5b9dec12016-05-16 15:40:5770#include "ui/gl/init/gl_factory.h"
[email protected]92dd77772013-08-01 23:57:5671
reveman27a01ff2014-12-20 00:19:0072#if defined(OS_WIN)
73#include <windows.h>
74#include "base/process/process_handle.h"
75#endif
76
[email protected]92dd77772013-08-01 23:57:5677namespace gpu {
78
79namespace {
80
tzik184a75bc2017-07-13 05:07:4181base::AtomicSequenceNumber g_next_command_buffer_id;
kylechar8eebde302017-08-22 21:50:3982base::AtomicSequenceNumber g_next_image_id;
dyen12e45962015-09-18 00:13:5183
[email protected]92dd77772013-08-01 23:57:5684template <typename T>
Jonathan Backerbd345c1f2018-02-14 21:44:2385base::OnceClosure WrapTaskWithResult(base::OnceCallback<T(void)> task,
86 T* result,
87 base::WaitableEvent* completion) {
88 auto wrapper = [](base::OnceCallback<T(void)> task, T* result,
89 base::WaitableEvent* completion) {
90 *result = std::move(task).Run();
91 completion->Signal();
92 };
93 return base::BindOnce(wrapper, std::move(task), result, completion);
[email protected]92dd77772013-08-01 23:57:5694}
95
fsamueledc0c2c2016-11-18 22:28:0496class GpuInProcessThreadHolder : public base::Thread {
97 public:
98 GpuInProcessThreadHolder()
kylechar2fdaa042018-07-03 17:36:2399 : base::Thread("GpuThread"),
100 sync_point_manager_(std::make_unique<SyncPointManager>()) {
fsamueledc0c2c2016-11-18 22:28:04101 Start();
dyenac45ecf2015-11-06 17:40:56102 }
103
fsamueledc0c2c2016-11-18 22:28:04104 ~GpuInProcessThreadHolder() override { Stop(); }
105
Zhenyao Mo56b32be2017-08-25 22:59:30106 void SetGpuFeatureInfo(const GpuFeatureInfo& gpu_feature_info) {
107 DCHECK(!gpu_thread_service_.get());
108 gpu_feature_info_ = gpu_feature_info;
109 }
110
kylechar2fdaa042018-07-03 17:36:23111 scoped_refptr<CommandBufferTaskExecutor> GetGpuThreadService() {
fsamueledc0c2c2016-11-18 22:28:04112 if (!gpu_thread_service_) {
Jonathan Backer7bc44592018-04-25 19:59:50113 DCHECK(base::CommandLine::InitializedForCurrentProcess());
114 const base::CommandLine* command_line =
115 base::CommandLine::ForCurrentProcess();
Jonathan Backer76dfd502018-05-03 18:34:31116 GpuPreferences gpu_preferences = gles2::ParseGpuPreferences(command_line);
117 gpu_preferences.texture_target_exception_list =
118 CreateBufferUsageAndFormatExceptionList();
kylechar47df6302018-02-14 01:45:48119 gpu_thread_service_ = base::MakeRefCounted<GpuInProcessThreadService>(
Jonathan Backerf2776922018-04-25 18:31:26120 task_runner(), sync_point_manager_.get(), nullptr, nullptr,
Jonathan Backer76dfd502018-05-03 18:34:31121 gpu_feature_info_, gpu_preferences);
fsamueledc0c2c2016-11-18 22:28:04122 }
123 return gpu_thread_service_;
dyenac45ecf2015-11-06 17:40:56124 }
125
126 private:
fsamueledc0c2c2016-11-18 22:28:04127 std::unique_ptr<SyncPointManager> sync_point_manager_;
kylechar2fdaa042018-07-03 17:36:23128 scoped_refptr<CommandBufferTaskExecutor> gpu_thread_service_;
Zhenyao Mo56b32be2017-08-25 22:59:30129 GpuFeatureInfo gpu_feature_info_;
boliu23adcfd2014-11-27 17:45:53130};
131
scottmg5e65e3a2017-03-08 08:48:46132base::LazyInstance<GpuInProcessThreadHolder>::DestructorAtExit
kylechar2fdaa042018-07-03 17:36:23133 g_default_task_executer = LAZY_INSTANCE_INITIALIZER;
[email protected]92dd77772013-08-01 23:57:56134
135class ScopedEvent {
136 public:
dcastagna504d45c2015-04-06 19:30:39137 explicit ScopedEvent(base::WaitableEvent* event) : event_(event) {}
[email protected]92dd77772013-08-01 23:57:56138 ~ScopedEvent() { event_->Signal(); }
139
140 private:
141 base::WaitableEvent* event_;
142};
143
kylechar2fdaa042018-07-03 17:36:23144// If |task_executer| is passed in then it will be returned, otherwise a default
145// task_executer will be constructed and returned.
146scoped_refptr<CommandBufferTaskExecutor> MaybeGetDefaultTaskExecutor(
147 scoped_refptr<CommandBufferTaskExecutor> task_executer) {
148 if (task_executer)
149 return task_executer;
hendrikw5c1da6d2015-06-18 15:08:57150
151 // Call base::ThreadTaskRunnerHandle::IsSet() to ensure that it is
152 // instantiated before we create the GPU thread, otherwise shutdown order will
153 // delete the ThreadTaskRunnerHandle before the GPU thread's message loop,
154 // and when the message loop is shutdown, it will recreate
155 // ThreadTaskRunnerHandle, which will re-add a new task to the, AtExitManager,
156 // which causes a deadlock because it's already locked.
157 base::ThreadTaskRunnerHandle::IsSet();
kylechar2fdaa042018-07-03 17:36:23158 return g_default_task_executer.Get().GetGpuThreadService();
hendrikw5c1da6d2015-06-18 15:08:57159}
160
[email protected]92dd77772013-08-01 23:57:56161} // anonyous namespace
162
Sadrul Habib Chowdhury7102df0b2018-05-30 03:04:17163const int InProcessCommandBuffer::kGpuClientId =
164 std::numeric_limits<int>::max();
Christopher Cameron9656d1f2018-01-28 09:23:19165
[email protected]aeb316d2014-02-13 14:25:25166InProcessCommandBuffer::InProcessCommandBuffer(
kylechar2fdaa042018-07-03 17:36:23167 scoped_refptr<CommandBufferTaskExecutor> task_executer)
sunnypsc8cc93e272017-03-21 20:52:27168 : command_buffer_id_(CommandBufferId::FromUnsafeValue(
169 g_next_command_buffer_id.GetNext() + 1)),
gabca50ffb2016-06-01 23:59:04170 flush_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
171 base::WaitableEvent::InitialState::NOT_SIGNALED),
kylechar2fdaa042018-07-03 17:36:23172 task_executor_(MaybeGetDefaultTaskExecutor(std::move(task_executer))),
gabca50ffb2016-06-01 23:59:04173 fence_sync_wait_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
174 base::WaitableEvent::InitialState::NOT_SIGNALED),
danakj10057772016-04-12 19:35:44175 client_thread_weak_ptr_factory_(this),
[email protected]aeb316d2014-02-13 14:25:25176 gpu_thread_weak_ptr_factory_(this) {
kylechar2fdaa042018-07-03 17:36:23177 DCHECK(task_executor_.get());
[email protected]aeb316d2014-02-13 14:25:25178}
[email protected]92dd77772013-08-01 23:57:56179
180InProcessCommandBuffer::~InProcessCommandBuffer() {
181 Destroy();
182}
183
Zhenyao Mo56b32be2017-08-25 22:59:30184// static
185void InProcessCommandBuffer::InitializeDefaultServiceForTesting(
186 const GpuFeatureInfo& gpu_feature_info) {
187 // Call base::ThreadTaskRunnerHandle::IsSet() to ensure that it is
188 // instantiated before we create the GPU thread, otherwise shutdown order will
189 // delete the ThreadTaskRunnerHandle before the GPU thread's message loop,
190 // and when the message loop is shutdown, it will recreate
191 // ThreadTaskRunnerHandle, which will re-add a new task to the, AtExitManager,
192 // which causes a deadlock because it's already locked.
193 base::ThreadTaskRunnerHandle::IsSet();
kylechar2fdaa042018-07-03 17:36:23194 g_default_task_executer.Get().SetGpuFeatureInfo(gpu_feature_info);
Zhenyao Mo56b32be2017-08-25 22:59:30195}
196
Jonathan Backer862b08d2018-05-10 15:37:04197gpu::ServiceTransferCache* InProcessCommandBuffer::GetTransferCacheForTest()
198 const {
199 return static_cast<raster::RasterDecoder*>(decoder_.get())
200 ->GetTransferCacheForTest();
201}
202
[email protected]92dd77772013-08-01 23:57:56203bool InProcessCommandBuffer::MakeCurrent() {
[email protected]61724842013-08-07 09:46:09204 CheckSequencedThread();
[email protected]92dd77772013-08-01 23:57:56205 command_buffer_lock_.AssertAcquired();
206
Antoine Laboure7e2da62017-05-25 00:28:26207 if (error::IsError(command_buffer_->GetState().error)) {
danakj07925222016-04-07 21:19:27208 DLOG(ERROR) << "MakeCurrent failed because context lost.";
209 return false;
210 }
211 if (!decoder_->MakeCurrent()) {
212 DLOG(ERROR) << "Context lost because MakeCurrent failed.";
Chandan Padhi07f05c02017-09-19 02:52:53213 command_buffer_->SetParseError(error::kLostContext);
danakj07925222016-04-07 21:19:27214 return false;
215 }
216 return true;
[email protected]92dd77772013-08-01 23:57:56217}
218
danakj45cfd232017-10-18 19:31:31219gpu::ContextResult InProcessCommandBuffer::Initialize(
kylechar7a463842016-05-26 14:46:12220 scoped_refptr<gl::GLSurface> surface,
[email protected]92dd77772013-08-01 23:57:56221 bool is_offscreen,
fsamueledc0c2c2016-11-18 22:28:04222 SurfaceHandle window,
Antoine Labourfeab2392017-12-21 20:28:39223 const ContextCreationAttribs& attribs,
reveman2232bce2014-10-29 01:28:05224 InProcessCommandBuffer* share_group,
225 GpuMemoryBufferManager* gpu_memory_buffer_manager,
ericrkd989e6a2016-09-19 21:17:04226 ImageFactory* image_factory,
kylechar8e7c5e4d2017-12-04 23:43:17227 GpuChannelManagerDelegate* gpu_channel_manager_delegate,
ericrkd989e6a2016-09-19 21:17:04228 scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
kylechar2fdaa042018-07-03 17:36:23229 DCHECK(!share_group ||
230 task_executor_.get() == share_group->task_executor_.get());
[email protected]92dd77772013-08-01 23:57:56231
kylechar8e7c5e4d2017-12-04 23:43:17232 gpu_memory_buffer_manager_ = gpu_memory_buffer_manager;
233 gpu_channel_manager_delegate_ = gpu_channel_manager_delegate;
234
danakj10057772016-04-12 19:35:44235 if (surface) {
ericrkd989e6a2016-09-19 21:17:04236 // If a surface is provided, we are running in a webview and should not have
237 // a task runner.
238 DCHECK(!task_runner);
239
[email protected]61724842013-08-07 09:46:09240 // GPU thread must be the same as client thread due to GLSurface not being
241 // thread safe.
242 sequence_checker_.reset(new base::SequenceChecker);
243 surface_ = surface;
danakj10057772016-04-12 19:35:44244 } else {
ericrkd989e6a2016-09-19 21:17:04245 DCHECK(task_runner);
246 origin_task_runner_ = std::move(task_runner);
danakj10057772016-04-12 19:35:44247 client_thread_weak_ptr_ = client_thread_weak_ptr_factory_.GetWeakPtr();
[email protected]61724842013-08-07 09:46:09248 }
249
Chandan Padhi07f05c02017-09-19 02:52:53250 Capabilities capabilities;
pimand488e8b42016-06-30 19:06:59251 InitializeOnGpuThreadParams params(is_offscreen, window, attribs,
252 &capabilities, share_group, image_factory);
[email protected]6d668892013-12-04 21:37:12253
Jonathan Backerbd345c1f2018-02-14 21:44:23254 base::OnceCallback<gpu::ContextResult(void)> init_task =
255 base::BindOnce(&InProcessCommandBuffer::InitializeOnGpuThread,
256 base::Unretained(this), params);
[email protected]61724842013-08-07 09:46:09257
gabca50ffb2016-06-01 23:59:04258 base::WaitableEvent completion(
259 base::WaitableEvent::ResetPolicy::MANUAL,
260 base::WaitableEvent::InitialState::NOT_SIGNALED);
danakj45cfd232017-10-18 19:31:31261 gpu::ContextResult result = gpu::ContextResult::kSuccess;
Jonathan Backerbd345c1f2018-02-14 21:44:23262 QueueOnceTask(true,
263 WrapTaskWithResult(std::move(init_task), &result, &completion));
[email protected]92dd77772013-08-01 23:57:56264 completion.Wait();
[email protected]6d668892013-12-04 21:37:12265
danakj45cfd232017-10-18 19:31:31266 if (result == gpu::ContextResult::kSuccess)
[email protected]6d668892013-12-04 21:37:12267 capabilities_ = capabilities;
revemanec103f02014-09-29 19:12:31268
[email protected]92dd77772013-08-01 23:57:56269 return result;
270}
271
danakj45cfd232017-10-18 19:31:31272gpu::ContextResult InProcessCommandBuffer::InitializeOnGpuThread(
[email protected]6d668892013-12-04 21:37:12273 const InitializeOnGpuThreadParams& params) {
[email protected]61724842013-08-07 09:46:09274 CheckSequencedThread();
[email protected]3f0855c02013-10-09 07:56:25275 gpu_thread_weak_ptr_ = gpu_thread_weak_ptr_factory_.GetWeakPtr();
[email protected]92dd77772013-08-01 23:57:56276
kylechar22b56412018-04-13 15:58:21277 // TODO(crbug.com/832243): This could use the TransferBufferManager owned by
278 // |context_group_| instead.
Jeremy Roman5c4533292017-10-16 23:13:54279 transfer_buffer_manager_ = std::make_unique<TransferBufferManager>(nullptr);
[email protected]92dd77772013-08-01 23:57:56280
Khushaldb2d4ad72018-07-03 22:36:27281 GpuDriverBugWorkarounds workarounds(
282 task_executor_->gpu_feature_info().enabled_gpu_driver_bug_workarounds);
kylechar22b56412018-04-13 15:58:21283 if (params.share_command_buffer) {
284 context_group_ = params.share_command_buffer->context_group_;
285 } else {
Jonathan Backera57031b2018-06-04 15:44:32286 auto feature_info = base::MakeRefCounted<gles2::FeatureInfo>(
kylechar2fdaa042018-07-03 17:36:23287 workarounds, task_executor_->gpu_feature_info());
[email protected]92dd77772013-08-01 23:57:56288
kylechar22b56412018-04-13 15:58:21289 context_group_ = base::MakeRefCounted<gles2::ContextGroup>(
kylechar2fdaa042018-07-03 17:36:23290 task_executor_->gpu_preferences(),
kylechar22b56412018-04-13 15:58:21291 gles2::PassthroughCommandDecoderSupported(),
kylechar2fdaa042018-07-03 17:36:23292 task_executor_->mailbox_manager(), nullptr /* memory_tracker */,
293 task_executor_->shader_translator_cache(),
294 task_executor_->framebuffer_completeness_cache(), feature_info,
295 params.attribs.bind_generates_resource, task_executor_->image_manager(),
Jonathan Backer76dfd502018-05-03 18:34:31296 params.image_factory, nullptr /* progress_reporter */,
kylechar2fdaa042018-07-03 17:36:23297 task_executor_->gpu_feature_info(),
298 task_executor_->discardable_manager());
kylechar22b56412018-04-13 15:58:21299 }
fsamueledc0c2c2016-11-18 22:28:04300
kylechar22b56412018-04-13 15:58:21301#if defined(OS_MACOSX)
302 // Virtualize PreferIntegratedGpu contexts by default on OS X to prevent
303 // performance regressions when enabling FCM. https://crbug.com/180463
304 use_virtualized_gl_context_ |=
305 (params.attribs.gpu_preference == gl::PreferIntegratedGpu);
306#endif
307
kylechar2fdaa042018-07-03 17:36:23308 use_virtualized_gl_context_ |= task_executor_->ForceVirtualizedGLContexts();
kylechar22b56412018-04-13 15:58:21309
310 // MailboxManagerSync synchronization correctness currently depends on having
311 // only a single context. See https://crbug.com/510243 for details.
kylechar2fdaa042018-07-03 17:36:23312 use_virtualized_gl_context_ |= task_executor_->mailbox_manager()->UsesSync();
kylechar22b56412018-04-13 15:58:21313
314 use_virtualized_gl_context_ |=
315 context_group_->feature_info()->workarounds().use_virtualized_gl_contexts;
fsamueledc0c2c2016-11-18 22:28:04316
Jeremy Roman5c4533292017-10-16 23:13:54317 command_buffer_ = std::make_unique<CommandBufferService>(
Antoine Labour1bec1072017-06-06 19:37:03318 this, transfer_buffer_manager_.get());
Jonathan Backer0cd1c4322018-04-17 16:57:10319
danakj45cfd232017-10-18 19:31:31320 if (!surface_) {
fsamueledc0c2c2016-11-18 22:28:04321 if (params.is_offscreen) {
kylechar22b56412018-04-13 15:58:21322 // TODO(crbug.com/832243): GLES2CommandBufferStub has additional logic for
323 // offscreen surfaces that might be needed here.
pimand488e8b42016-06-30 19:06:59324 surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size());
kylechar22b56412018-04-13 15:58:21325 if (!surface_.get()) {
326 DestroyOnGpuThread();
327 LOG(ERROR) << "ContextResult::kFatalFailure: Failed to create surface.";
danakj45cfd232017-10-18 19:31:31328 return gpu::ContextResult::kFatalFailure;
fsamueledc0c2c2016-11-18 22:28:04329 }
kylechar22b56412018-04-13 15:58:21330 } else {
331 gl::GLSurfaceFormat surface_format;
332 switch (params.attribs.color_space) {
333 case COLOR_SPACE_UNSPECIFIED:
334 surface_format.SetColorSpace(
335 gl::GLSurfaceFormat::COLOR_SPACE_UNSPECIFIED);
336 break;
337 case COLOR_SPACE_SRGB:
338 surface_format.SetColorSpace(gl::GLSurfaceFormat::COLOR_SPACE_SRGB);
339 break;
340 case COLOR_SPACE_DISPLAY_P3:
341 surface_format.SetColorSpace(
342 gl::GLSurfaceFormat::COLOR_SPACE_DISPLAY_P3);
343 break;
344 }
345 surface_ = ImageTransportSurface::CreateNativeSurface(
346 gpu_thread_weak_ptr_factory_.GetWeakPtr(), params.window,
347 surface_format);
348 if (!surface_ || !surface_->Initialize(surface_format)) {
349 DestroyOnGpuThread();
350 LOG(ERROR) << "ContextResult::kFatalFailure: Failed to create surface.";
351 return gpu::ContextResult::kFatalFailure;
352 }
353 if (params.attribs.enable_swap_timestamps_if_supported &&
354 surface_->SupportsSwapTimestamps())
355 surface_->SetEnableSwapTimestamps();
fsamueledc0c2c2016-11-18 22:28:04356 }
[email protected]61724842013-08-07 09:46:09357 }
[email protected]92dd77772013-08-01 23:57:56358
kylechar22b56412018-04-13 15:58:21359 // TODO(crbug.com/832243): InProcessCommandBuffer should support using the GPU
360 // scheduler for non-WebView cases.
sunnypsc8cc93e272017-03-21 20:52:27361 sync_point_order_data_ =
kylechar2fdaa042018-07-03 17:36:23362 task_executor_->sync_point_manager()->CreateSyncPointOrderData();
sunnypsc8cc93e272017-03-21 20:52:27363 sync_point_client_state_ =
kylechar2fdaa042018-07-03 17:36:23364 task_executor_->sync_point_manager()->CreateSyncPointClientState(
sunnypsc8cc93e272017-03-21 20:52:27365 GetNamespaceID(), GetCommandBufferID(),
366 sync_point_order_data_->sequence_id());
dyena6b0d39a2015-09-22 21:53:26367
kylechar22b56412018-04-13 15:58:21368 if (context_group_->use_passthrough_cmd_decoder()) {
369 // When using the passthrough command decoder, only share with other
370 // contexts in the explicitly requested share group.
371 if (params.share_command_buffer) {
372 gl_share_group_ = params.share_command_buffer->gl_share_group_;
373 } else {
374 gl_share_group_ = new gl::GLShareGroup();
375 }
376 } else {
377 // When using the validating command decoder, always use the global share
378 // group.
kylechar2fdaa042018-07-03 17:36:23379 gl_share_group_ = task_executor_->share_group();
kylechar22b56412018-04-13 15:58:21380 }
Sunny Sachanandani93c2ec12017-06-30 03:26:45381
382 // TODO(sunnyps): Should this use ScopedCrashKey instead?
Robert Sesekd7329222017-12-08 15:31:08383 crash_keys::gpu_gl_context_is_virtual.Set(use_virtualized_gl_context_ ? "1"
384 : "0");
Sunny Sachanandani93c2ec12017-06-30 03:26:45385
Khushaldb2d4ad72018-07-03 22:36:27386 // TODO(khushalsagar): A lot of this initialization code is duplicated in
387 // GpuChannelManager. Pull it into a common util method.
388 scoped_refptr<gl::GLContext> real_context =
389 use_virtualized_gl_context_
390 ? gl_share_group_->GetSharedContext(surface_.get())
391 : nullptr;
392 if (!real_context) {
393 real_context = gl::init::CreateGLContext(
394 gl_share_group_.get(), surface_.get(),
395 GenerateGLContextAttribs(params.attribs, context_group_.get()));
396 if (!real_context) {
397 // TODO(piman): This might not be fatal, we could recurse into
398 // CreateGLContext to get more info, tho it should be exceedingly
399 // rare and may not be recoverable anyway.
400 DestroyOnGpuThread();
401 LOG(ERROR) << "ContextResult::kFatalFailure: "
402 "Failed to create shared context for virtualization.";
403 return gpu::ContextResult::kFatalFailure;
[email protected]92dd77772013-08-01 23:57:56404 }
Khushaldb2d4ad72018-07-03 22:36:27405 // Ensure that context creation did not lose track of the intended share
406 // group.
407 DCHECK(real_context->share_group() == gl_share_group_.get());
408 task_executor_->gpu_feature_info().ApplyToGLContext(real_context.get());
[email protected]92dd77772013-08-01 23:57:56409
Khushaldb2d4ad72018-07-03 22:36:27410 if (use_virtualized_gl_context_)
411 gl_share_group_->SetSharedContext(surface_.get(), real_context.get());
412 }
413
414 if (!real_context->MakeCurrent(surface_.get())) {
415 LOG(ERROR)
416 << "ContextResult::kTransientFailure, failed to make context current";
417 DestroyOnGpuThread();
418 return ContextResult::kTransientFailure;
419 }
420
421 bool supports_oop_rasterization =
422 task_executor_->gpu_feature_info()
423 .status_values[GPU_FEATURE_TYPE_OOP_RASTERIZATION] ==
424 kGpuFeatureStatusEnabled;
425 if (supports_oop_rasterization && params.attribs.enable_oop_rasterization &&
426 params.attribs.enable_raster_interface &&
427 !params.attribs.enable_gles2_interface) {
428 scoped_refptr<raster::RasterDecoderContextState> context_state =
429 new raster::RasterDecoderContextState(gl_share_group_, surface_,
430 real_context,
431 use_virtualized_gl_context_);
432 context_state->InitializeGrContext(workarounds);
433
434 decoder_.reset(raster::RasterDecoder::Create(
435 this, command_buffer_.get(), task_executor_->outputter(),
436 context_group_.get(), std::move(context_state)));
437 } else {
438 decoder_.reset(gles2::GLES2Decoder::Create(this, command_buffer_.get(),
439 task_executor_->outputter(),
440 context_group_.get()));
441 }
442
443 if (use_virtualized_gl_context_) {
kylechar22b56412018-04-13 15:58:21444 context_ = base::MakeRefCounted<GLContextVirtual>(
445 gl_share_group_.get(), real_context.get(), decoder_->AsWeakPtr());
446 if (!context_->Initialize(
447 surface_.get(),
448 GenerateGLContextAttribs(params.attribs, context_group_.get()))) {
449 // TODO(piman): This might not be fatal, we could recurse into
450 // CreateGLContext to get more info, tho it should be exceedingly
451 // rare and may not be recoverable anyway.
452 DestroyOnGpuThread();
453 LOG(ERROR) << "ContextResult::kFatalFailure: "
454 "Failed to initialize virtual GL context.";
455 return gpu::ContextResult::kFatalFailure;
[email protected]92dd77772013-08-01 23:57:56456 }
Khushaldb2d4ad72018-07-03 22:36:27457
458 if (!context_->MakeCurrent(surface_.get())) {
kylechar22b56412018-04-13 15:58:21459 DestroyOnGpuThread();
Khushaldb2d4ad72018-07-03 22:36:27460 // The caller should retry making a context, but this one won't work.
461 LOG(ERROR) << "ContextResult::kTransientFailure: "
462 "Could not make context current.";
463 return gpu::ContextResult::kTransientFailure;
Zhenyao Mo56b32be2017-08-25 22:59:30464 }
[email protected]92dd77772013-08-01 23:57:56465
kylechar22b56412018-04-13 15:58:21466 context_->SetGLStateRestorer(
467 new GLStateRestorerImpl(decoder_->AsWeakPtr()));
Khushaldb2d4ad72018-07-03 22:36:27468 } else {
469 context_ = real_context;
470 DCHECK(context_->IsCurrent(surface_.get()));
kylechar22b56412018-04-13 15:58:21471 }
472
473 if (!context_group_->has_program_cache() &&
474 !context_group_->feature_info()->workarounds().disable_program_cache) {
kylechar2fdaa042018-07-03 17:36:23475 context_group_->set_program_cache(task_executor_->program_cache());
boliua9987672015-08-26 22:51:21476 }
477
[email protected]92dd77772013-08-01 23:57:56478 gles2::DisallowedFeatures disallowed_features;
danakj45cfd232017-10-18 19:31:31479 auto result = decoder_->Initialize(surface_, context_, params.is_offscreen,
480 disallowed_features, params.attribs);
481 if (result != gpu::ContextResult::kSuccess) {
[email protected]92dd77772013-08-01 23:57:56482 DestroyOnGpuThread();
kylechar22b56412018-04-13 15:58:21483 DLOG(ERROR) << "Failed to initialize decoder.";
danakj45cfd232017-10-18 19:31:31484 return result;
[email protected]92dd77772013-08-01 23:57:56485 }
kylechar22b56412018-04-13 15:58:21486
kylechar2fdaa042018-07-03 17:36:23487 if (task_executor_->gpu_preferences().enable_gpu_service_logging)
Jonathan Backer0cd1c4322018-04-17 16:57:10488 decoder_->SetLogCommands(true);
kylechar22b56412018-04-13 15:58:21489
490 if (use_virtualized_gl_context_) {
491 // If virtualized GL contexts are in use, then real GL context state
492 // is in an indeterminate state, since the GLStateRestorer was not
493 // initialized at the time the GLContextVirtual was made current. In
494 // the case that this command decoder is the next one to be
495 // processed, force a "full virtual" MakeCurrent to be performed.
496 context_->ForceReleaseVirtuallyCurrent();
497 if (!context_->MakeCurrent(surface_.get())) {
498 DestroyOnGpuThread();
499 LOG(ERROR) << "ContextResult::kTransientFailure: "
500 "Failed to make context current after initialization.";
501 return gpu::ContextResult::kTransientFailure;
502 }
503 }
504
[email protected]01952a62014-05-02 05:22:01505 *params.capabilities = decoder_->GetCapabilities();
[email protected]92dd77772013-08-01 23:57:56506
reveman2232bce2014-10-29 01:28:05507 image_factory_ = params.image_factory;
reveman2232bce2014-10-29 01:28:05508
danakj45cfd232017-10-18 19:31:31509 return gpu::ContextResult::kSuccess;
[email protected]92dd77772013-08-01 23:57:56510}
511
512void InProcessCommandBuffer::Destroy() {
[email protected]61724842013-08-07 09:46:09513 CheckSequencedThread();
danakj10057772016-04-12 19:35:44514 client_thread_weak_ptr_factory_.InvalidateWeakPtrs();
515 gpu_control_client_ = nullptr;
gabca50ffb2016-06-01 23:59:04516 base::WaitableEvent completion(
517 base::WaitableEvent::ResetPolicy::MANUAL,
518 base::WaitableEvent::InitialState::NOT_SIGNALED);
[email protected]caa43eb2013-08-03 01:52:28519 bool result = false;
Jonathan Backerbd345c1f2018-02-14 21:44:23520 base::OnceCallback<bool(void)> destroy_task = base::BindOnce(
[email protected]92dd77772013-08-01 23:57:56521 &InProcessCommandBuffer::DestroyOnGpuThread, base::Unretained(this));
Jonathan Backerbd345c1f2018-02-14 21:44:23522 QueueOnceTask(
523 true, WrapTaskWithResult(std::move(destroy_task), &result, &completion));
[email protected]92dd77772013-08-01 23:57:56524 completion.Wait();
525}
526
527bool InProcessCommandBuffer::DestroyOnGpuThread() {
[email protected]61724842013-08-07 09:46:09528 CheckSequencedThread();
Sunny Sachanandani6cec39432017-07-06 17:33:29529 // TODO(sunnyps): Should this use ScopedCrashKey instead?
Robert Sesekd7329222017-12-08 15:31:08530 crash_keys::gpu_gl_context_is_virtual.Set(use_virtualized_gl_context_ ? "1"
531 : "0");
[email protected]3f0855c02013-10-09 07:56:25532 gpu_thread_weak_ptr_factory_.InvalidateWeakPtrs();
[email protected]92dd77772013-08-01 23:57:56533 // Clean up GL resources if possible.
Daniel Cheng3d7ce9f2014-08-26 00:26:25534 bool have_context = context_.get() && context_->MakeCurrent(surface_.get());
Christopher Cameron78ad7b112018-05-09 18:25:01535
536 // Prepare to destroy the surface while the context is still current, because
537 // some surface destructors make GL calls.
538 if (surface_)
539 surface_->PrepareToDestroy(have_context);
540
[email protected]92dd77772013-08-01 23:57:56541 if (decoder_) {
542 decoder_->Destroy(have_context);
543 decoder_.reset();
544 }
Antoine Labour1bec1072017-06-06 19:37:03545 command_buffer_.reset();
danakj10057772016-04-12 19:35:44546 surface_ = nullptr;
Christopher Cameron3505eac2018-02-22 10:00:24547
548 context_ = nullptr;
dyen5c38a032015-10-07 18:58:31549 if (sync_point_order_data_) {
550 sync_point_order_data_->Destroy();
551 sync_point_order_data_ = nullptr;
552 }
sunnypsc8cc93e272017-03-21 20:52:27553 if (sync_point_client_state_) {
554 sync_point_client_state_->Destroy();
555 sync_point_client_state_ = nullptr;
556 }
danakj10057772016-04-12 19:35:44557 gl_share_group_ = nullptr;
tzik684418e2017-02-15 05:48:29558 context_group_ = nullptr;
[email protected]92dd77772013-08-01 23:57:56559
fsamueledc0c2c2016-11-18 22:28:04560 base::AutoLock lock(task_queue_lock_);
Brett Wilsona62d9c02017-09-20 20:53:20561 base::queue<std::unique_ptr<GpuTask>> empty;
fsamueledc0c2c2016-11-18 22:28:04562 task_queue_.swap(empty);
563
[email protected]92dd77772013-08-01 23:57:56564 return true;
565}
566
[email protected]61724842013-08-07 09:46:09567void InProcessCommandBuffer::CheckSequencedThread() {
fdoraye2b19a12016-07-29 02:30:16568 DCHECK(!sequence_checker_ || sequence_checker_->CalledOnValidSequence());
[email protected]61724842013-08-07 09:46:09569}
570
Antoine Labour293e93e2017-05-26 18:19:11571CommandBufferServiceClient::CommandBatchProcessedResult
572InProcessCommandBuffer::OnCommandBatchProcessed() {
573 return kContinueExecution;
574}
575
576void InProcessCommandBuffer::OnParseError() {
danakj10057772016-04-12 19:35:44577 if (!origin_task_runner_)
578 return OnContextLost(); // Just kidding, we're on the client thread.
579 origin_task_runner_->PostTask(
580 FROM_HERE, base::Bind(&InProcessCommandBuffer::OnContextLost,
581 client_thread_weak_ptr_));
582}
583
[email protected]92dd77772013-08-01 23:57:56584void InProcessCommandBuffer::OnContextLost() {
[email protected]61724842013-08-07 09:46:09585 CheckSequencedThread();
danakj10057772016-04-12 19:35:44586
587#if DCHECK_IS_ON()
588 // This method shouldn't be called more than once.
589 DCHECK(!context_lost_);
590 context_lost_ = true;
591#endif
592
593 if (gpu_control_client_)
594 gpu_control_client_->OnGpuControlLostContext();
[email protected]92dd77772013-08-01 23:57:56595}
596
Jonathan Backerbd345c1f2018-02-14 21:44:23597void InProcessCommandBuffer::QueueOnceTask(bool out_of_order,
598 base::OnceClosure task) {
fsamueledc0c2c2016-11-18 22:28:04599 if (out_of_order) {
kylechar2fdaa042018-07-03 17:36:23600 task_executor_->ScheduleTask(std::move(task));
fsamueledc0c2c2016-11-18 22:28:04601 return;
602 }
603 // Release the |task_queue_lock_| before calling ScheduleTask because
604 // the callback may get called immediately and attempt to acquire the lock.
sunnypsc8cc93e272017-03-21 20:52:27605 uint32_t order_num = sync_point_order_data_->GenerateUnprocessedOrderNumber();
fsamueledc0c2c2016-11-18 22:28:04606 {
607 base::AutoLock lock(task_queue_lock_);
Jonathan Backerbd345c1f2018-02-14 21:44:23608 std::unique_ptr<GpuTask> gpu_task =
609 std::make_unique<GpuTask>(std::move(task), order_num);
610 task_queue_.push(std::move(gpu_task));
611 }
kylechar2fdaa042018-07-03 17:36:23612 task_executor_->ScheduleTask(base::BindOnce(
Jonathan Backerbd345c1f2018-02-14 21:44:23613 &InProcessCommandBuffer::ProcessTasksOnGpuThread, gpu_thread_weak_ptr_));
614}
615
616void InProcessCommandBuffer::QueueRepeatableTask(base::RepeatingClosure task) {
617 // Release the |task_queue_lock_| before calling ScheduleTask because
618 // the callback may get called immediately and attempt to acquire the lock.
619 uint32_t order_num = sync_point_order_data_->GenerateUnprocessedOrderNumber();
620 {
621 base::AutoLock lock(task_queue_lock_);
622 std::unique_ptr<GpuTask> gpu_task =
623 std::make_unique<GpuTask>(std::move(task), order_num);
624 task_queue_.push(std::move(gpu_task));
fsamueledc0c2c2016-11-18 22:28:04625 }
kylechar2fdaa042018-07-03 17:36:23626 task_executor_->ScheduleTask(base::BindOnce(
fsamueledc0c2c2016-11-18 22:28:04627 &InProcessCommandBuffer::ProcessTasksOnGpuThread, gpu_thread_weak_ptr_));
628}
629
630void InProcessCommandBuffer::ProcessTasksOnGpuThread() {
Sunny Sachanandani93c2ec12017-06-30 03:26:45631 // TODO(sunnyps): Should this use ScopedCrashKey instead?
Robert Sesekd7329222017-12-08 15:31:08632 crash_keys::gpu_gl_context_is_virtual.Set(use_virtualized_gl_context_ ? "1"
633 : "0");
Antoine Labourbe0c1282017-05-25 23:04:10634 while (command_buffer_->scheduled()) {
fsamueledc0c2c2016-11-18 22:28:04635 base::AutoLock lock(task_queue_lock_);
636 if (task_queue_.empty())
637 break;
638 GpuTask* task = task_queue_.front().get();
Jonathan Backerbd345c1f2018-02-14 21:44:23639 sync_point_order_data_->BeginProcessingOrderNumber(task->order_number());
640 task->Run();
Antoine Labourbe0c1282017-05-25 23:04:10641 if (!command_buffer_->scheduled() &&
kylechar2fdaa042018-07-03 17:36:23642 !task_executor_->BlockThreadOnWaitSyncToken()) {
Jonathan Backerbd345c1f2018-02-14 21:44:23643 sync_point_order_data_->PauseProcessingOrderNumber(task->order_number());
mfomitchev426ea5dd2017-04-14 03:03:39644 // Don't pop the task if it was preempted - it may have been preempted, so
645 // we need to execute it again later.
Jonathan Backerbd345c1f2018-02-14 21:44:23646 DCHECK(task->is_repeatable());
fsamueledc0c2c2016-11-18 22:28:04647 return;
648 }
Jonathan Backerbd345c1f2018-02-14 21:44:23649 sync_point_order_data_->FinishProcessingOrderNumber(task->order_number());
fsamueledc0c2c2016-11-18 22:28:04650 task_queue_.pop();
651 }
652}
653
[email protected]92dd77772013-08-01 23:57:56654CommandBuffer::State InProcessCommandBuffer::GetLastState() {
[email protected]61724842013-08-07 09:46:09655 CheckSequencedThread();
sunnyps128566052016-12-09 21:06:43656 base::AutoLock lock(last_state_lock_);
[email protected]92dd77772013-08-01 23:57:56657 return last_state_;
658}
659
sunnyps128566052016-12-09 21:06:43660void InProcessCommandBuffer::UpdateLastStateOnGpuThread() {
[email protected]61724842013-08-07 09:46:09661 CheckSequencedThread();
sunnyps128566052016-12-09 21:06:43662 command_buffer_lock_.AssertAcquired();
663 base::AutoLock lock(last_state_lock_);
Antoine Laboure7e2da62017-05-25 00:28:26664 command_buffer_->UpdateState();
665 State state = command_buffer_->GetState();
sunnyps128566052016-12-09 21:06:43666 if (state.generation - last_state_.generation < 0x80000000U)
667 last_state_ = state;
[email protected]63936fca2013-08-07 05:18:54668}
[email protected]92dd77772013-08-01 23:57:56669
Sadrul Habib Chowdhury89a1fbde2018-06-14 17:00:41670void InProcessCommandBuffer::FlushOnGpuThread(int32_t put_offset) {
[email protected]61724842013-08-07 09:46:09671 CheckSequencedThread();
[email protected]63936fca2013-08-07 05:18:54672 ScopedEvent handle_flush(&flush_event_);
[email protected]92dd77772013-08-01 23:57:56673 base::AutoLock lock(command_buffer_lock_);
dyena6b0d39a2015-09-22 21:53:26674
Antoine Labour689c26a2017-05-25 19:15:44675 if (!MakeCurrent())
676 return;
677
Antoine Labour1bec1072017-06-06 19:37:03678 command_buffer_->Flush(put_offset, decoder_.get());
sunnyps128566052016-12-09 21:06:43679 // Update state before signaling the flush event.
680 UpdateLastStateOnGpuThread();
dyena6b0d39a2015-09-22 21:53:26681
[email protected]3f0855c02013-10-09 07:56:25682 // If we've processed all pending commands but still have pending queries,
683 // pump idle work until the query is passed.
Antoine Laboure7e2da62017-05-25 00:28:26684 if (put_offset == command_buffer_->GetState().get_offset &&
Antoine Labour3aaa590f2017-05-24 00:34:34685 (decoder_->HasMoreIdleWork() || decoder_->HasPendingQueries())) {
reveman87580eb2015-09-17 21:45:22686 ScheduleDelayedWorkOnGpuThread();
[email protected]3f0855c02013-10-09 07:56:25687 }
688}
689
danakj10057772016-04-12 19:35:44690void InProcessCommandBuffer::PerformDelayedWorkOnGpuThread() {
[email protected]3f0855c02013-10-09 07:56:25691 CheckSequencedThread();
reveman87580eb2015-09-17 21:45:22692 delayed_work_pending_ = false;
[email protected]3f0855c02013-10-09 07:56:25693 base::AutoLock lock(command_buffer_lock_);
Sunny Sachanandani93c2ec12017-06-30 03:26:45694 // TODO(sunnyps): Should this use ScopedCrashKey instead?
Robert Sesekd7329222017-12-08 15:31:08695 crash_keys::gpu_gl_context_is_virtual.Set(use_virtualized_gl_context_ ? "1"
696 : "0");
reveman87580eb2015-09-17 21:45:22697 if (MakeCurrent()) {
Antoine Labour3aaa590f2017-05-24 00:34:34698 decoder_->PerformIdleWork();
699 decoder_->ProcessPendingQueries(false);
700 if (decoder_->HasMoreIdleWork() || decoder_->HasPendingQueries()) {
reveman87580eb2015-09-17 21:45:22701 ScheduleDelayedWorkOnGpuThread();
702 }
[email protected]3f0855c02013-10-09 07:56:25703 }
[email protected]92dd77772013-08-01 23:57:56704}
705
reveman87580eb2015-09-17 21:45:22706void InProcessCommandBuffer::ScheduleDelayedWorkOnGpuThread() {
[email protected]0d830e6b2014-08-08 09:41:41707 CheckSequencedThread();
reveman87580eb2015-09-17 21:45:22708 if (delayed_work_pending_)
[email protected]0d830e6b2014-08-08 09:41:41709 return;
reveman87580eb2015-09-17 21:45:22710 delayed_work_pending_ = true;
kylechar2fdaa042018-07-03 17:36:23711 task_executor_->ScheduleDelayedWork(
danakj10057772016-04-12 19:35:44712 base::Bind(&InProcessCommandBuffer::PerformDelayedWorkOnGpuThread,
713 gpu_thread_weak_ptr_));
[email protected]0d830e6b2014-08-08 09:41:41714}
715
avif15d60a2015-12-21 17:06:33716void InProcessCommandBuffer::Flush(int32_t put_offset) {
[email protected]61724842013-08-07 09:46:09717 CheckSequencedThread();
Chandan Padhi07f05c02017-09-19 02:52:53718 if (GetLastState().error != error::kNoError)
[email protected]92dd77772013-08-01 23:57:56719 return;
720
721 if (last_put_offset_ == put_offset)
722 return;
723
724 last_put_offset_ = put_offset;
Sadrul Habib Chowdhury89a1fbde2018-06-14 17:00:41725 base::RepeatingClosure task =
726 base::BindRepeating(&InProcessCommandBuffer::FlushOnGpuThread,
727 gpu_thread_weak_ptr_, put_offset);
Jonathan Backerbd345c1f2018-02-14 21:44:23728 QueueRepeatableTask(std::move(task));
dyen5c38a032015-10-07 18:58:31729
730 flushed_fence_sync_release_ = next_fence_sync_release_ - 1;
[email protected]92dd77772013-08-01 23:57:56731}
732
avif15d60a2015-12-21 17:06:33733void InProcessCommandBuffer::OrderingBarrier(int32_t put_offset) {
vmiurab700b432015-02-06 16:42:51734 Flush(put_offset);
735}
736
sunnyps128566052016-12-09 21:06:43737CommandBuffer::State InProcessCommandBuffer::WaitForTokenInRange(int32_t start,
738 int32_t end) {
[email protected]61724842013-08-07 09:46:09739 CheckSequencedThread();
sunnyps128566052016-12-09 21:06:43740 State last_state = GetLastState();
741 while (!InRange(start, end, last_state.token) &&
Chandan Padhi07f05c02017-09-19 02:52:53742 last_state.error == error::kNoError) {
[email protected]7fe4198b2014-03-18 21:52:36743 flush_event_.Wait();
sunnyps128566052016-12-09 21:06:43744 last_state = GetLastState();
fsamueledc0c2c2016-11-18 22:28:04745 }
sunnyps128566052016-12-09 21:06:43746 return last_state;
[email protected]7fe4198b2014-03-18 21:52:36747}
[email protected]92dd77772013-08-01 23:57:56748
sunnyps128566052016-12-09 21:06:43749CommandBuffer::State InProcessCommandBuffer::WaitForGetOffsetInRange(
Antoine Labourd3469942017-05-16 21:23:42750 uint32_t set_get_buffer_count,
sunnyps128566052016-12-09 21:06:43751 int32_t start,
752 int32_t end) {
[email protected]7fe4198b2014-03-18 21:52:36753 CheckSequencedThread();
sunnyps128566052016-12-09 21:06:43754 State last_state = GetLastState();
Antoine Labourd3469942017-05-16 21:23:42755 while (((set_get_buffer_count != last_state.set_get_buffer_count) ||
756 !InRange(start, end, last_state.get_offset)) &&
Chandan Padhi07f05c02017-09-19 02:52:53757 last_state.error == error::kNoError) {
[email protected]92dd77772013-08-01 23:57:56758 flush_event_.Wait();
sunnyps128566052016-12-09 21:06:43759 last_state = GetLastState();
[email protected]92dd77772013-08-01 23:57:56760 }
sunnyps128566052016-12-09 21:06:43761 return last_state;
[email protected]92dd77772013-08-01 23:57:56762}
763
avif15d60a2015-12-21 17:06:33764void InProcessCommandBuffer::SetGetBuffer(int32_t shm_id) {
[email protected]61724842013-08-07 09:46:09765 CheckSequencedThread();
Chandan Padhi07f05c02017-09-19 02:52:53766 if (GetLastState().error != error::kNoError)
[email protected]92dd77772013-08-01 23:57:56767 return;
768
gabca50ffb2016-06-01 23:59:04769 base::WaitableEvent completion(
770 base::WaitableEvent::ResetPolicy::MANUAL,
771 base::WaitableEvent::InitialState::NOT_SIGNALED);
Jonathan Backerbd345c1f2018-02-14 21:44:23772 base::OnceClosure task =
773 base::BindOnce(&InProcessCommandBuffer::SetGetBufferOnGpuThread,
774 base::Unretained(this), shm_id, &completion);
775 QueueOnceTask(false, std::move(task));
vmpstrd3435c6cd2015-06-13 00:31:25776 completion.Wait();
777
sunnyps128566052016-12-09 21:06:43778 last_put_offset_ = 0;
[email protected]92dd77772013-08-01 23:57:56779}
780
vmpstrd3435c6cd2015-06-13 00:31:25781void InProcessCommandBuffer::SetGetBufferOnGpuThread(
avif15d60a2015-12-21 17:06:33782 int32_t shm_id,
vmpstrd3435c6cd2015-06-13 00:31:25783 base::WaitableEvent* completion) {
784 base::AutoLock lock(command_buffer_lock_);
785 command_buffer_->SetGetBuffer(shm_id);
sunnyps128566052016-12-09 21:06:43786 UpdateLastStateOnGpuThread();
vmpstrd3435c6cd2015-06-13 00:31:25787 completion->Signal();
788}
789
avif15d60a2015-12-21 17:06:33790scoped_refptr<Buffer> InProcessCommandBuffer::CreateTransferBuffer(
791 size_t size,
792 int32_t* id) {
[email protected]61724842013-08-07 09:46:09793 CheckSequencedThread();
[email protected]92dd77772013-08-01 23:57:56794 base::AutoLock lock(command_buffer_lock_);
795 return command_buffer_->CreateTransferBuffer(size, id);
796}
797
avif15d60a2015-12-21 17:06:33798void InProcessCommandBuffer::DestroyTransferBuffer(int32_t id) {
[email protected]61724842013-08-07 09:46:09799 CheckSequencedThread();
Jonathan Backerbd345c1f2018-02-14 21:44:23800 base::OnceClosure task =
801 base::BindOnce(&InProcessCommandBuffer::DestroyTransferBufferOnGpuThread,
802 base::Unretained(this), id);
[email protected]92dd77772013-08-01 23:57:56803
Jonathan Backerbd345c1f2018-02-14 21:44:23804 QueueOnceTask(false, std::move(task));
[email protected]92dd77772013-08-01 23:57:56805}
806
avif15d60a2015-12-21 17:06:33807void InProcessCommandBuffer::DestroyTransferBufferOnGpuThread(int32_t id) {
[email protected]02f1e6a2014-04-11 21:08:36808 base::AutoLock lock(command_buffer_lock_);
809 command_buffer_->DestroyTransferBuffer(id);
810}
811
danakj10057772016-04-12 19:35:44812void InProcessCommandBuffer::SetGpuControlClient(GpuControlClient* client) {
813 gpu_control_client_ = client;
814}
815
Zhenyao Moeb86a1712017-10-06 14:17:52816const Capabilities& InProcessCommandBuffer::GetCapabilities() const {
[email protected]6d668892013-12-04 21:37:12817 return capabilities_;
[email protected]744e0792013-09-27 01:18:35818}
819
Zhenyao Mo04ea0f02017-10-12 01:15:54820const GpuFeatureInfo& InProcessCommandBuffer::GetGpuFeatureInfo() const {
kylechar2fdaa042018-07-03 17:36:23821 return task_executor_->gpu_feature_info();
Zhenyao Mo04ea0f02017-10-12 01:15:54822}
823
avif15d60a2015-12-21 17:06:33824int32_t InProcessCommandBuffer::CreateImage(ClientBuffer buffer,
825 size_t width,
826 size_t height,
827 unsigned internalformat) {
reveman2232bce2014-10-29 01:28:05828 CheckSequencedThread();
829
830 DCHECK(gpu_memory_buffer_manager_);
831 gfx::GpuMemoryBuffer* gpu_memory_buffer =
sadrul849cb9e2016-11-09 17:19:45832 reinterpret_cast<gfx::GpuMemoryBuffer*>(buffer);
reveman2232bce2014-10-29 01:28:05833 DCHECK(gpu_memory_buffer);
834
kylechar8eebde302017-08-22 21:50:39835 int32_t new_id = g_next_image_id.GetNext() + 1;
reveman2232bce2014-10-29 01:28:05836
Chandan Padhi07f05c02017-09-19 02:52:53837 DCHECK(IsImageFromGpuMemoryBufferFormatSupported(
ccameronc1fcde52017-04-12 19:40:49838 gpu_memory_buffer->GetFormat(), capabilities_));
Chandan Padhi07f05c02017-09-19 02:52:53839 DCHECK(IsImageFormatCompatibleWithGpuMemoryBufferFormat(
reveman2232bce2014-10-29 01:28:05840 internalformat, gpu_memory_buffer->GetFormat()));
reveman27a01ff2014-12-20 00:19:00841
842 // This handle is owned by the GPU thread and must be passed to it or it
843 // will leak. In otherwords, do not early out on error between here and the
844 // queuing of the CreateImage task below.
sadrul73794ca2016-11-29 04:10:07845 gfx::GpuMemoryBufferHandle handle =
846 gfx::CloneHandleForIPC(gpu_memory_buffer->GetHandle());
847 bool requires_sync_point = handle.type == gfx::IO_SURFACE_BUFFER;
reveman27a01ff2014-12-20 00:19:00848
dyenac45ecf2015-11-06 17:40:56849 uint64_t fence_sync = 0;
nhirokia1ab22a2015-11-05 05:56:05850 if (requires_sync_point) {
dyenac45ecf2015-11-06 17:40:56851 fence_sync = GenerateFenceSyncRelease();
852
853 // Previous fence syncs should be flushed already.
854 DCHECK_EQ(fence_sync - 1, flushed_fence_sync_release_);
855 }
856
Jonathan Backerbd345c1f2018-02-14 21:44:23857 QueueOnceTask(
858 false,
859 base::BindOnce(&InProcessCommandBuffer::CreateImageOnGpuThread,
Alexandr Ilind82fcd82018-06-25 17:47:38860 base::Unretained(this), new_id, std::move(handle),
Jonathan Backerbd345c1f2018-02-14 21:44:23861 gfx::Size(base::checked_cast<int>(width),
862 base::checked_cast<int>(height)),
863 gpu_memory_buffer->GetFormat(),
864 base::checked_cast<uint32_t>(internalformat), fence_sync));
dyenac45ecf2015-11-06 17:40:56865
866 if (fence_sync) {
867 flushed_fence_sync_release_ = fence_sync;
Sunny Sachanandanidb1759e2017-12-20 22:33:21868 SyncToken sync_token(GetNamespaceID(), GetCommandBufferID(), fence_sync);
dyenac45ecf2015-11-06 17:40:56869 sync_token.SetVerifyFlush();
870 gpu_memory_buffer_manager_->SetDestructionSyncToken(gpu_memory_buffer,
871 sync_token);
reveman27a01ff2014-12-20 00:19:00872 }
873
reveman2232bce2014-10-29 01:28:05874 return new_id;
875}
876
877void InProcessCommandBuffer::CreateImageOnGpuThread(
avif15d60a2015-12-21 17:06:33878 int32_t id,
Alexandr Ilind82fcd82018-06-25 17:47:38879 gfx::GpuMemoryBufferHandle handle,
reveman2232bce2014-10-29 01:28:05880 const gfx::Size& size,
spangfcf5fab42015-08-04 19:25:35881 gfx::BufferFormat format,
avif15d60a2015-12-21 17:06:33882 uint32_t internalformat,
dyenac45ecf2015-11-06 17:40:56883 uint64_t fence_sync) {
kylechar2fdaa042018-07-03 17:36:23884 gles2::ImageManager* image_manager = task_executor_->image_manager();
reveman2232bce2014-10-29 01:28:05885 DCHECK(image_manager);
886 if (image_manager->LookupImage(id)) {
887 LOG(ERROR) << "Image already exists with same ID.";
888 return;
889 }
890
reveman5f717f82015-05-21 23:21:07891 switch (handle.type) {
892 case gfx::SHARED_MEMORY_BUFFER: {
reveman730fd9612015-11-11 01:22:43893 if (!base::IsValueInRangeForNumericType<size_t>(handle.stride)) {
894 LOG(ERROR) << "Invalid stride for image.";
895 return;
896 }
tfarinadf856e022015-10-29 12:50:45897 scoped_refptr<gl::GLImageSharedMemory> image(
898 new gl::GLImageSharedMemory(size, internalformat));
reveman730fd9612015-11-11 01:22:43899 if (!image->Initialize(handle.handle, handle.id, format, handle.offset,
900 handle.stride)) {
reveman5f717f82015-05-21 23:21:07901 LOG(ERROR) << "Failed to initialize image.";
902 return;
903 }
reveman2232bce2014-10-29 01:28:05904
reveman5f717f82015-05-21 23:21:07905 image_manager->AddImage(image.get(), id);
906 break;
907 }
908 default: {
909 if (!image_factory_) {
910 LOG(ERROR) << "Image factory missing but required by buffer type.";
911 return;
912 }
reveman2232bce2014-10-29 01:28:05913
tfarinadf856e022015-10-29 12:50:45914 scoped_refptr<gl::GLImage> image =
reveman5f717f82015-05-21 23:21:07915 image_factory_->CreateImageForGpuMemoryBuffer(
Alexandr Ilind82fcd82018-06-25 17:47:38916 std::move(handle), size, format, internalformat, kGpuClientId,
reveman15e3d9a2016-07-19 18:21:12917 kNullSurfaceHandle);
reveman5f717f82015-05-21 23:21:07918 if (!image.get()) {
919 LOG(ERROR) << "Failed to create image for buffer.";
920 return;
921 }
922
923 image_manager->AddImage(image.get(), id);
924 break;
925 }
926 }
dyenac45ecf2015-11-06 17:40:56927
sunnyps9147a5312017-03-02 20:26:37928 if (fence_sync)
sunnypsc8cc93e272017-03-21 20:52:27929 sync_point_client_state_->ReleaseFenceSync(fence_sync);
reveman22dd9292014-10-13 20:52:05930}
931
avif15d60a2015-12-21 17:06:33932void InProcessCommandBuffer::DestroyImage(int32_t id) {
reveman2232bce2014-10-29 01:28:05933 CheckSequencedThread();
934
Jonathan Backerbd345c1f2018-02-14 21:44:23935 QueueOnceTask(false,
936 base::BindOnce(&InProcessCommandBuffer::DestroyImageOnGpuThread,
937 base::Unretained(this), id));
reveman2232bce2014-10-29 01:28:05938}
939
avif15d60a2015-12-21 17:06:33940void InProcessCommandBuffer::DestroyImageOnGpuThread(int32_t id) {
kylechar2fdaa042018-07-03 17:36:23941 gles2::ImageManager* image_manager = task_executor_->image_manager();
reveman2232bce2014-10-29 01:28:05942 DCHECK(image_manager);
943 if (!image_manager->LookupImage(id)) {
944 LOG(ERROR) << "Image with ID doesn't exist.";
945 return;
946 }
947
948 image_manager->RemoveImage(id);
reveman22dd9292014-10-13 20:52:05949}
950
Antoine Labourf679fa42017-06-07 00:32:43951void InProcessCommandBuffer::OnConsoleMessage(int32_t id,
952 const std::string& message) {
953 // TODO(piman): implement this.
954}
955
956void InProcessCommandBuffer::CacheShader(const std::string& key,
957 const std::string& shader) {
Sadrul Habib Chowdhury7102df0b2018-05-30 03:04:17958 if (gpu_channel_manager_delegate_)
959 gpu_channel_manager_delegate_->StoreShaderToDisk(kGpuClientId, key, shader);
Antoine Labourf679fa42017-06-07 00:32:43960}
961
962void InProcessCommandBuffer::OnFenceSyncRelease(uint64_t release) {
Sunny Sachanandanidb1759e2017-12-20 22:33:21963 SyncToken sync_token(GetNamespaceID(), GetCommandBufferID(), release);
sunnyps9147a5312017-03-02 20:26:37964
kylechar22b56412018-04-13 15:58:21965 context_group_->mailbox_manager()->PushTextureUpdates(sync_token);
dyen5c38a032015-10-07 18:58:31966
sunnypsc8cc93e272017-03-21 20:52:27967 sync_point_client_state_->ReleaseFenceSync(release);
dyen5c38a032015-10-07 18:58:31968}
969
Antoine Labourf679fa42017-06-07 00:32:43970bool InProcessCommandBuffer::OnWaitSyncToken(const SyncToken& sync_token) {
fsamueledc0c2c2016-11-18 22:28:04971 DCHECK(!waiting_for_sync_point_);
kylechar2fdaa042018-07-03 17:36:23972 SyncPointManager* sync_point_manager = task_executor_->sync_point_manager();
dyen5c38a032015-10-07 18:58:31973 DCHECK(sync_point_manager);
974
kylechar22b56412018-04-13 15:58:21975 MailboxManager* mailbox_manager = context_group_->mailbox_manager();
sunnyps9147a5312017-03-02 20:26:37976 DCHECK(mailbox_manager);
dyen5c38a032015-10-07 18:58:31977
kylechar2fdaa042018-07-03 17:36:23978 if (task_executor_->BlockThreadOnWaitSyncToken()) {
sunnyps9147a5312017-03-02 20:26:37979 // Wait if sync point wait is valid.
sunnypsc8cc93e272017-03-21 20:52:27980 if (sync_point_client_state_->Wait(
sunnyps9147a5312017-03-02 20:26:37981 sync_token,
982 base::Bind(&base::WaitableEvent::Signal,
983 base::Unretained(&fence_sync_wait_event_)))) {
fsamueledc0c2c2016-11-18 22:28:04984 fence_sync_wait_event_.Wait();
985 }
986
fsamueledc0c2c2016-11-18 22:28:04987 mailbox_manager->PullTextureUpdates(sync_token);
sunnyps9147a5312017-03-02 20:26:37988 return false;
dyen5c38a032015-10-07 18:58:31989 }
990
sunnypsc8cc93e272017-03-21 20:52:27991 waiting_for_sync_point_ = sync_point_client_state_->Wait(
sunnyps9147a5312017-03-02 20:26:37992 sync_token,
993 base::Bind(&InProcessCommandBuffer::OnWaitSyncTokenCompleted,
994 gpu_thread_weak_ptr_factory_.GetWeakPtr(), sync_token));
995 if (!waiting_for_sync_point_) {
fsamueledc0c2c2016-11-18 22:28:04996 mailbox_manager->PullTextureUpdates(sync_token);
sunnyps9147a5312017-03-02 20:26:37997 return false;
fsamueledc0c2c2016-11-18 22:28:04998 }
999
Antoine Labourbe0c1282017-05-25 23:04:101000 command_buffer_->SetScheduled(false);
sunnyps9147a5312017-03-02 20:26:371001 return true;
fsamueledc0c2c2016-11-18 22:28:041002}
1003
sunnyps9147a5312017-03-02 20:26:371004void InProcessCommandBuffer::OnWaitSyncTokenCompleted(
1005 const SyncToken& sync_token) {
fsamueledc0c2c2016-11-18 22:28:041006 DCHECK(waiting_for_sync_point_);
kylechar22b56412018-04-13 15:58:211007 context_group_->mailbox_manager()->PullTextureUpdates(sync_token);
fsamueledc0c2c2016-11-18 22:28:041008 waiting_for_sync_point_ = false;
Antoine Labourbe0c1282017-05-25 23:04:101009 command_buffer_->SetScheduled(true);
kylechar2fdaa042018-07-03 17:36:231010 task_executor_->ScheduleTask(base::BindOnce(
mfomitchev995b74dc2017-04-12 22:55:181011 &InProcessCommandBuffer::ProcessTasksOnGpuThread, gpu_thread_weak_ptr_));
sievers173a20d2014-10-22 18:19:321012}
1013
Antoine Labourf679fa42017-06-07 00:32:431014void InProcessCommandBuffer::OnDescheduleUntilFinished() {
kylechar2fdaa042018-07-03 17:36:231015 if (!task_executor_->BlockThreadOnWaitSyncToken()) {
Antoine Labourbe0c1282017-05-25 23:04:101016 DCHECK(command_buffer_->scheduled());
Antoine Labour3aaa590f2017-05-24 00:34:341017 DCHECK(decoder_->HasPollingWork());
fsamueledc0c2c2016-11-18 22:28:041018
Antoine Labourbe0c1282017-05-25 23:04:101019 command_buffer_->SetScheduled(false);
fsamueledc0c2c2016-11-18 22:28:041020 }
erikchen13338b62016-06-01 03:58:181021}
1022
Antoine Labourf679fa42017-06-07 00:32:431023void InProcessCommandBuffer::OnRescheduleAfterFinished() {
kylechar2fdaa042018-07-03 17:36:231024 if (!task_executor_->BlockThreadOnWaitSyncToken()) {
Antoine Labourbe0c1282017-05-25 23:04:101025 DCHECK(!command_buffer_->scheduled());
fsamueledc0c2c2016-11-18 22:28:041026
Antoine Labourbe0c1282017-05-25 23:04:101027 command_buffer_->SetScheduled(true);
fsamueledc0c2c2016-11-18 22:28:041028 ProcessTasksOnGpuThread();
1029 }
erikchen13338b62016-06-01 03:58:181030}
1031
Eric Karlb6b2c632018-05-07 22:45:041032void InProcessCommandBuffer::OnSwapBuffers(uint64_t swap_id, uint32_t flags) {
1033 pending_swap_completed_params_.push_back({swap_id, flags});
Peng Huang606ca802018-05-18 15:50:021034 pending_presented_params_.push_back({swap_id, flags});
Eric Karlb6b2c632018-05-07 22:45:041035}
Peng Huang2a30e262018-05-02 21:08:591036
dyenae103dce2015-11-17 19:59:041037void InProcessCommandBuffer::SignalSyncTokenOnGpuThread(
fsamuel600b99e2016-11-11 07:50:261038 const SyncToken& sync_token,
Jonathan Backerbd345c1f2018-02-14 21:44:231039 base::OnceClosure callback) {
1040 base::RepeatingClosure maybe_pass_callback =
1041 base::AdaptCallbackForRepeating(WrapCallback(std::move(callback)));
1042 if (!sync_point_client_state_->Wait(sync_token, maybe_pass_callback)) {
1043 maybe_pass_callback.Run();
1044 }
dyenae103dce2015-11-17 19:59:041045}
1046
[email protected]b63f1d62014-07-18 15:40:591047void InProcessCommandBuffer::SignalQuery(unsigned query_id,
Jonathan Backerbd345c1f2018-02-14 21:44:231048 base::OnceClosure callback) {
[email protected]3f0855c02013-10-09 07:56:251049 CheckSequencedThread();
Jonathan Backerbd345c1f2018-02-14 21:44:231050 QueueOnceTask(false,
1051 base::BindOnce(&InProcessCommandBuffer::SignalQueryOnGpuThread,
1052 base::Unretained(this), query_id,
1053 WrapCallback(std::move(callback))));
[email protected]b88a48cc2013-10-05 05:10:101054}
1055
[email protected]b63f1d62014-07-18 15:40:591056void InProcessCommandBuffer::SignalQueryOnGpuThread(
1057 unsigned query_id,
Jonathan Backerbd345c1f2018-02-14 21:44:231058 base::OnceClosure callback) {
Geoff Lang85287e12018-05-22 17:26:401059 decoder_->SetQueryCallback(query_id, std::move(callback));
[email protected]b63f1d62014-07-18 15:40:591060}
1061
Klaus Weidnere66cc7d2017-12-09 17:26:301062void InProcessCommandBuffer::CreateGpuFence(uint32_t gpu_fence_id,
1063 ClientGpuFence source) {
1064 CheckSequencedThread();
1065
1066 // Pass a cloned handle to the GPU process since the source ClientGpuFence
1067 // may go out of scope before the queued task runs.
1068 gfx::GpuFence* gpu_fence = gfx::GpuFence::FromClientGpuFence(source);
1069 gfx::GpuFenceHandle handle =
1070 gfx::CloneHandleForIPC(gpu_fence->GetGpuFenceHandle());
1071
Jonathan Backerbd345c1f2018-02-14 21:44:231072 QueueOnceTask(
1073 false, base::BindOnce(&InProcessCommandBuffer::CreateGpuFenceOnGpuThread,
1074 base::Unretained(this), gpu_fence_id, handle));
Klaus Weidnere66cc7d2017-12-09 17:26:301075}
1076
1077void InProcessCommandBuffer::CreateGpuFenceOnGpuThread(
1078 uint32_t gpu_fence_id,
1079 const gfx::GpuFenceHandle& handle) {
1080 if (!GetFeatureInfo()->feature_flags().chromium_gpu_fence) {
1081 DLOG(ERROR) << "CHROMIUM_gpu_fence unavailable";
1082 command_buffer_->SetParseError(error::kLostContext);
1083 return;
1084 }
1085
1086 gles2::GpuFenceManager* gpu_fence_manager = decoder_->GetGpuFenceManager();
1087 DCHECK(gpu_fence_manager);
1088
1089 if (gpu_fence_manager->CreateGpuFenceFromHandle(gpu_fence_id, handle))
1090 return;
1091
1092 // The insertion failed. This shouldn't happen, force context loss to avoid
1093 // inconsistent state.
1094 command_buffer_->SetParseError(error::kLostContext);
1095}
1096
1097void InProcessCommandBuffer::GetGpuFence(
1098 uint32_t gpu_fence_id,
1099 base::OnceCallback<void(std::unique_ptr<gfx::GpuFence>)> callback) {
1100 CheckSequencedThread();
Klaus Weidnere66cc7d2017-12-09 17:26:301101 auto task_runner = base::ThreadTaskRunnerHandle::IsSet()
1102 ? base::ThreadTaskRunnerHandle::Get()
1103 : nullptr;
Jonathan Backerbd345c1f2018-02-14 21:44:231104 QueueOnceTask(
1105 false, base::BindOnce(&InProcessCommandBuffer::GetGpuFenceOnGpuThread,
1106 base::Unretained(this), gpu_fence_id, task_runner,
1107 std::move(callback)));
Klaus Weidnere66cc7d2017-12-09 17:26:301108}
1109
1110void InProcessCommandBuffer::GetGpuFenceOnGpuThread(
1111 uint32_t gpu_fence_id,
1112 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
1113 base::OnceCallback<void(std::unique_ptr<gfx::GpuFence>)> callback) {
1114 if (!GetFeatureInfo()->feature_flags().chromium_gpu_fence) {
1115 DLOG(ERROR) << "CHROMIUM_gpu_fence unavailable";
1116 command_buffer_->SetParseError(error::kLostContext);
1117 return;
1118 }
1119
1120 gles2::GpuFenceManager* manager = decoder_->GetGpuFenceManager();
1121 DCHECK(manager);
1122
1123 std::unique_ptr<gfx::GpuFence> gpu_fence;
1124 if (manager->IsValidGpuFence(gpu_fence_id)) {
1125 gpu_fence = manager->GetGpuFence(gpu_fence_id);
1126 } else {
1127 // Retrieval failed. This shouldn't happen, force context loss to avoid
1128 // inconsistent state.
1129 DLOG(ERROR) << "GpuFence not found";
1130 command_buffer_->SetParseError(error::kLostContext);
1131 }
1132
1133 // Execute callback on client thread using the supplied task_runner where
1134 // available, cf. WrapCallback and PostCallback.
1135 base::OnceClosure callback_closure =
1136 base::BindOnce(std::move(callback), std::move(gpu_fence));
1137 if (task_runner.get() && !task_runner->BelongsToCurrentThread()) {
1138 task_runner->PostTask(FROM_HERE, std::move(callback_closure));
1139 } else {
1140 std::move(callback_closure).Run();
1141 }
1142}
1143
jbauman6875d4e02015-02-12 00:44:591144void InProcessCommandBuffer::SetLock(base::Lock*) {
danakj07925222016-04-07 21:19:271145 // No support for using on multiple threads.
1146 NOTREACHED();
jbauman6875d4e02015-02-12 00:44:591147}
1148
dyen293de3c2016-01-05 02:08:051149void InProcessCommandBuffer::EnsureWorkVisible() {
1150 // This is only relevant for out-of-process command buffers.
1151}
1152
dyen12e45962015-09-18 00:13:511153CommandBufferNamespace InProcessCommandBuffer::GetNamespaceID() const {
1154 return CommandBufferNamespace::IN_PROCESS;
1155}
1156
lukasza2573ce7d2016-02-16 19:17:221157CommandBufferId InProcessCommandBuffer::GetCommandBufferID() const {
dyen12e45962015-09-18 00:13:511158 return command_buffer_id_;
1159}
1160
Sunny Sachanandani9b8fb342017-08-26 00:49:561161void InProcessCommandBuffer::FlushPendingWork() {
Sunny Sachanandani5f5419e22017-05-12 20:35:301162 // This is only relevant for out-of-process command buffers.
1163}
1164
dyen5c38a032015-10-07 18:58:311165uint64_t InProcessCommandBuffer::GenerateFenceSyncRelease() {
1166 return next_fence_sync_release_++;
1167}
1168
sunnyps128566052016-12-09 21:06:431169bool InProcessCommandBuffer::IsFenceSyncReleased(uint64_t release) {
1170 return release <= GetLastState().release_count;
1171}
1172
dyen6f3b4392015-10-22 20:17:231173void InProcessCommandBuffer::SignalSyncToken(const SyncToken& sync_token,
Jonathan Backerbd345c1f2018-02-14 21:44:231174 base::OnceClosure callback) {
dyenae103dce2015-11-17 19:59:041175 CheckSequencedThread();
Jonathan Backerbd345c1f2018-02-14 21:44:231176 QueueOnceTask(
1177 false, base::BindOnce(&InProcessCommandBuffer::SignalSyncTokenOnGpuThread,
1178 base::Unretained(this), sync_token,
1179 WrapCallback(std::move(callback))));
dyen6f3b4392015-10-22 20:17:231180}
1181
sunnyps74996292017-03-15 02:35:481182void InProcessCommandBuffer::WaitSyncTokenHint(const SyncToken& sync_token) {}
1183
dyen55719a12015-10-14 17:26:111184bool InProcessCommandBuffer::CanWaitUnverifiedSyncToken(
sunnyps74996292017-03-15 02:35:481185 const SyncToken& sync_token) {
1186 return sync_token.namespace_id() == GetNamespaceID();
dyen55719a12015-10-14 17:26:111187}
1188
fsamueledc0c2c2016-11-18 22:28:041189#if defined(OS_WIN)
1190void InProcessCommandBuffer::DidCreateAcceleratedSurfaceChildWindow(
1191 SurfaceHandle parent_window,
1192 SurfaceHandle child_window) {
kylechar8e7c5e4d2017-12-04 23:43:171193 // In the browser process call ::SetParent() directly.
1194 if (!gpu_channel_manager_delegate_) {
1195 ::SetParent(child_window, parent_window);
chaopengf77fb4f72018-01-19 20:31:421196 // Move D3D window behind Chrome's window to avoid losing some messages.
1197 ::SetWindowPos(child_window, HWND_BOTTOM, 0, 0, 0, 0,
1198 SWP_NOMOVE | SWP_NOSIZE);
kylechar8e7c5e4d2017-12-04 23:43:171199 return;
1200 }
1201
1202 // In the GPU process forward the request back to the browser process.
kylecharcd157cc2018-05-30 17:30:021203 gpu_channel_manager_delegate_->SendCreatedChildWindow(parent_window,
1204 child_window);
fsamueledc0c2c2016-11-18 22:28:041205}
1206#endif
1207
1208void InProcessCommandBuffer::DidSwapBuffersComplete(
1209 SwapBuffersCompleteParams params) {
Eric Karlb6b2c632018-05-07 22:45:041210 params.swap_response.swap_id = pending_swap_completed_params_.front().swap_id;
1211 pending_swap_completed_params_.pop_front();
1212
fsamuel58b5a222016-11-23 23:50:241213 if (!origin_task_runner_) {
1214 DidSwapBuffersCompleteOnOriginThread(std::move(params));
1215 return;
1216 }
1217 origin_task_runner_->PostTask(
1218 FROM_HERE,
1219 base::Bind(&InProcessCommandBuffer::DidSwapBuffersCompleteOnOriginThread,
1220 client_thread_weak_ptr_, base::Passed(&params)));
1221}
1222
1223const gles2::FeatureInfo* InProcessCommandBuffer::GetFeatureInfo() const {
1224 return context_group_->feature_info();
1225}
1226
John Bauman39210ea2017-07-27 23:11:551227const GpuPreferences& InProcessCommandBuffer::GetGpuPreferences() const {
1228 return context_group_->gpu_preferences();
1229}
1230
Peng Huang6bf92772017-11-30 18:57:081231void InProcessCommandBuffer::BufferPresented(
Peng Huang6bf92772017-11-30 18:57:081232 const gfx::PresentationFeedback& feedback) {
Jonathan Backer57ecd002018-05-23 13:20:311233 SwapBufferParams params = pending_presented_params_.front();
Eric Karlb6b2c632018-05-07 22:45:041234 pending_presented_params_.pop_front();
1235
Peng Huang6bf92772017-11-30 18:57:081236 if (!origin_task_runner_) {
Eric Karlb6b2c632018-05-07 22:45:041237 BufferPresentedOnOriginThread(params.swap_id, params.flags, feedback);
Peng Huang6bf92772017-11-30 18:57:081238 return;
1239 }
1240 origin_task_runner_->PostTask(
1241 FROM_HERE,
1242 base::Bind(&InProcessCommandBuffer::BufferPresentedOnOriginThread,
Eric Karlb6b2c632018-05-07 22:45:041243 client_thread_weak_ptr_, params.swap_id, params.flags,
1244 feedback));
Peng Huang6bf92772017-11-30 18:57:081245}
1246
stanisceed2187b2017-02-15 19:56:051247void InProcessCommandBuffer::AddFilter(IPC::MessageFilter* message_filter) {
1248 NOTREACHED();
1249}
1250
1251int32_t InProcessCommandBuffer::GetRouteID() const {
1252 NOTREACHED();
1253 return 0;
1254}
1255
fsamuel58b5a222016-11-23 23:50:241256void InProcessCommandBuffer::DidSwapBuffersCompleteOnOriginThread(
1257 SwapBuffersCompleteParams params) {
Eric Karlb6b2c632018-05-07 22:45:041258 if (gpu_control_client_)
1259 gpu_control_client_->OnGpuControlSwapBuffersCompleted(params);
fsamueledc0c2c2016-11-18 22:28:041260}
1261
Peng Huang6bf92772017-11-30 18:57:081262void InProcessCommandBuffer::BufferPresentedOnOriginThread(
1263 uint64_t swap_id,
Eric Karlb6b2c632018-05-07 22:45:041264 uint32_t flags,
Peng Huang6bf92772017-11-30 18:57:081265 const gfx::PresentationFeedback& feedback) {
Sadrul Habib Chowdhuryf74aa5cb2018-05-19 01:08:031266 if (gpu_control_client_)
1267 gpu_control_client_->OnSwapBufferPresented(swap_id, feedback);
Eric Karlb6b2c632018-05-07 22:45:041268 if (flags & gpu::SwapBuffersFlags::kPresentationFeedback ||
1269 (flags & gpu::SwapBuffersFlags::kVSyncParams &&
1270 feedback.flags & gfx::PresentationFeedback::kVSync)) {
Eric Karlb6b2c632018-05-07 22:45:041271 if (update_vsync_parameters_completion_callback_ &&
1272 feedback.timestamp != base::TimeTicks())
1273 update_vsync_parameters_completion_callback_.Run(feedback.timestamp,
1274 feedback.interval);
1275 }
fsamueledc0c2c2016-11-18 22:28:041276}
1277
1278void InProcessCommandBuffer::SetUpdateVSyncParametersCallback(
1279 const UpdateVSyncParametersCallback& callback) {
1280 update_vsync_parameters_completion_callback_ = callback;
1281}
1282
[email protected]92dd77772013-08-01 23:57:561283namespace {
1284
skyostil0ad2c542015-05-07 11:52:011285void PostCallback(
1286 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
Jonathan Backerbd345c1f2018-02-14 21:44:231287 base::OnceClosure callback) {
skyostil0ad2c542015-05-07 11:52:011288 // The task_runner.get() check is to support using InProcessCommandBuffer on
1289 // a thread without a message loop.
1290 if (task_runner.get() && !task_runner->BelongsToCurrentThread()) {
Jonathan Backerbd345c1f2018-02-14 21:44:231291 task_runner->PostTask(FROM_HERE, std::move(callback));
[email protected]92dd77772013-08-01 23:57:561292 } else {
Jonathan Backerbd345c1f2018-02-14 21:44:231293 std::move(callback).Run();
[email protected]92dd77772013-08-01 23:57:561294 }
1295}
1296
Jonathan Backerbd345c1f2018-02-14 21:44:231297void RunOnTargetThread(base::OnceClosure callback) {
1298 DCHECK(!callback.is_null());
1299 std::move(callback).Run();
[email protected]92dd77772013-08-01 23:57:561300}
1301
1302} // anonymous namespace
1303
Jonathan Backerbd345c1f2018-02-14 21:44:231304base::OnceClosure InProcessCommandBuffer::WrapCallback(
1305 base::OnceClosure callback) {
[email protected]92dd77772013-08-01 23:57:561306 // Make sure the callback gets deleted on the target thread by passing
1307 // ownership.
Jonathan Backerbd345c1f2018-02-14 21:44:231308 base::OnceClosure callback_on_client_thread =
1309 base::BindOnce(&RunOnTargetThread, std::move(callback));
1310 base::OnceClosure wrapped_callback =
1311 base::BindOnce(&PostCallback,
1312 base::ThreadTaskRunnerHandle::IsSet()
1313 ? base::ThreadTaskRunnerHandle::Get()
1314 : nullptr,
1315 std::move(callback_on_client_thread));
[email protected]92dd77772013-08-01 23:57:561316 return wrapped_callback;
1317}
1318
Jonathan Backerbd345c1f2018-02-14 21:44:231319InProcessCommandBuffer::GpuTask::GpuTask(base::OnceClosure callback,
fsamueledc0c2c2016-11-18 22:28:041320 uint32_t order_number)
Jonathan Backerbd345c1f2018-02-14 21:44:231321 : once_closure_(std::move(callback)), order_number_(order_number) {}
1322
1323InProcessCommandBuffer::GpuTask::GpuTask(base::RepeatingClosure callback,
1324 uint32_t order_number)
1325 : repeating_closure_(std::move(callback)), order_number_(order_number) {}
boliuc5befe72015-07-21 19:08:561326
Chris Watkins81030772017-12-07 01:20:561327InProcessCommandBuffer::GpuTask::~GpuTask() = default;
boliuc5befe72015-07-21 19:08:561328
Jonathan Backerbd345c1f2018-02-14 21:44:231329void InProcessCommandBuffer::GpuTask::Run() {
1330 if (once_closure_) {
1331 std::move(once_closure_).Run();
1332 return;
1333 }
1334 DCHECK(repeating_closure_) << "Trying to run a OnceClosure more than once.";
1335 repeating_closure_.Run();
1336}
1337
[email protected]92dd77772013-08-01 23:57:561338} // namespace gpu