[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 1 | // 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 | |
fsamuel | 600b99e | 2016-11-11 07:50:26 | [diff] [blame] | 5 | #include "gpu/ipc/in_process_command_buffer.h" |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 6 | |
avi | f15d60a | 2015-12-21 17:06:33 | [diff] [blame] | 7 | #include <stddef.h> |
| 8 | #include <stdint.h> |
| 9 | |
[email protected] | efaff84 | 2014-02-25 18:13:27 | [diff] [blame] | 10 | #include <set> |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 11 | #include <utility> |
| 12 | |
kylechar | 8eebde30 | 2017-08-22 21:50:39 | [diff] [blame] | 13 | #include "base/atomic_sequence_num.h" |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 14 | #include "base/bind.h" |
| 15 | #include "base/bind_helpers.h" |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 16 | #include "base/callback_helpers.h" |
boliu | a998767 | 2015-08-26 22:51:21 | [diff] [blame] | 17 | #include "base/command_line.h" |
Brett Wilson | a62d9c0 | 2017-09-20 20:53:20 | [diff] [blame] | 18 | #include "base/containers/queue.h" |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 19 | #include "base/lazy_instance.h" |
skyostil | 0ad2c54 | 2015-05-07 11:52:01 | [diff] [blame] | 20 | #include "base/location.h" |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 21 | #include "base/logging.h" |
| 22 | #include "base/memory/weak_ptr.h" |
reveman | 730fd961 | 2015-11-11 01:22:43 | [diff] [blame] | 23 | #include "base/numerics/safe_conversions.h" |
[email protected] | 6172484 | 2013-08-07 09:46:09 | [diff] [blame] | 24 | #include "base/sequence_checker.h" |
skyostil | 0ad2c54 | 2015-05-07 11:52:01 | [diff] [blame] | 25 | #include "base/single_thread_task_runner.h" |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 26 | #include "base/threading/thread.h" |
gab | b2370531 | 2016-05-11 18:44:56 | [diff] [blame] | 27 | #include "base/threading/thread_task_runner_handle.h" |
Kevin Marshall | 03cda64 | 2017-08-16 22:27:05 | [diff] [blame] | 28 | #include "build/build_config.h" |
danakj | 1005777 | 2016-04-12 19:35:44 | [diff] [blame] | 29 | #include "gpu/command_buffer/client/gpu_control_client.h" |
reveman | 2232bce | 2014-10-29 01:28:05 | [diff] [blame] | 30 | #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" |
penghuang | cfa7cae | 2016-04-06 21:11:50 | [diff] [blame] | 31 | #include "gpu/command_buffer/common/gpu_memory_buffer_support.h" |
Christopher Cameron | 4bc282bb | 2017-12-03 11:24:05 | [diff] [blame] | 32 | #include "gpu/command_buffer/common/swap_buffers_complete_params.h" |
Eric Karl | b6b2c63 | 2018-05-07 22:45:04 | [diff] [blame] | 33 | #include "gpu/command_buffer/common/swap_buffers_flags.h" |
dyen | 1e5cd82 | 2015-10-12 18:07:09 | [diff] [blame] | 34 | #include "gpu/command_buffer/common/sync_token.h" |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 35 | #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" |
kylechar | 22b5641 | 2018-04-13 15:58:21 | [diff] [blame] | 38 | #include "gpu/command_buffer/service/gl_state_restorer_impl.h" |
Jonathan Backer | 0cd1c432 | 2018-04-17 16:57:10 | [diff] [blame] | 39 | #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
Klaus Weidner | e66cc7d | 2017-12-09 17:26:30 | [diff] [blame] | 40 | #include "gpu/command_buffer/service/gpu_fence_manager.h" |
Chandan Padhi | 07f05c0 | 2017-09-19 02:52:53 | [diff] [blame] | 41 | #include "gpu/command_buffer/service/gpu_tracer.h" |
reveman | 2232bce | 2014-10-29 01:28:05 | [diff] [blame] | 42 | #include "gpu/command_buffer/service/image_factory.h" |
Antoine Labour | 40b0ca4 | 2018-01-03 20:15:34 | [diff] [blame] | 43 | #include "gpu/command_buffer/service/mailbox_manager_factory.h" |
boliu | a998767 | 2015-08-26 22:51:21 | [diff] [blame] | 44 | #include "gpu/command_buffer/service/memory_program_cache.h" |
dcheng | 6ef3c555 | 2014-08-30 05:34:19 | [diff] [blame] | 45 | #include "gpu/command_buffer/service/memory_tracking.h" |
[email protected] | b63f1d6 | 2014-07-18 15:40:59 | [diff] [blame] | 46 | #include "gpu/command_buffer/service/query_manager.h" |
Jonathan Backer | 0cd1c432 | 2018-04-17 16:57:10 | [diff] [blame] | 47 | #include "gpu/command_buffer/service/raster_decoder.h" |
Khushal | db2d4ad7 | 2018-07-03 22:36:27 | [diff] [blame^] | 48 | #include "gpu/command_buffer/service/raster_decoder_context_state.h" |
geofflang | df7fff2d4 | 2016-11-11 00:34:03 | [diff] [blame] | 49 | #include "gpu/command_buffer/service/service_utils.h" |
boliu | 0aa0158b | 2015-02-11 04:06:01 | [diff] [blame] | 50 | #include "gpu/command_buffer/service/sync_point_manager.h" |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 51 | #include "gpu/command_buffer/service/transfer_buffer_manager.h" |
Sunny Sachanandani | 93c2ec1 | 2017-06-30 03:26:45 | [diff] [blame] | 52 | #include "gpu/config/gpu_crash_keys.h" |
ericrk | 41a1579e | 2017-02-10 20:56:28 | [diff] [blame] | 53 | #include "gpu/config/gpu_feature_info.h" |
Jonathan Backer | 0af50996 | 2018-05-30 16:05:07 | [diff] [blame] | 54 | #include "gpu/config/gpu_preferences.h" |
Jonathan Backer | eba6af4 | 2018-05-03 22:47:43 | [diff] [blame] | 55 | #include "gpu/config/gpu_switches.h" |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 56 | #include "gpu/ipc/command_buffer_task_executor.h" |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 57 | #include "gpu/ipc/gpu_in_process_thread_service.h" |
Jonathan Backer | 76dfd50 | 2018-05-03 18:34:31 | [diff] [blame] | 58 | #include "gpu/ipc/host/gpu_memory_buffer_support.h" |
kylechar | 8e7c5e4d | 2017-12-04 23:43:17 | [diff] [blame] | 59 | #include "gpu/ipc/service/gpu_channel_manager_delegate.h" |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 60 | #include "gpu/ipc/service/image_transport_surface.h" |
tfarina | ebe974f0 | 2015-01-03 04:25:32 | [diff] [blame] | 61 | #include "ui/gfx/geometry/size.h" |
Klaus Weidner | e66cc7d | 2017-12-09 17:26:30 | [diff] [blame] | 62 | #include "ui/gfx/gpu_fence.h" |
| 63 | #include "ui/gfx/gpu_fence_handle.h" |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 64 | #include "ui/gl/gl_context.h" |
| 65 | #include "ui/gl/gl_image.h" |
reveman | 5f717f8 | 2015-05-21 23:21:07 | [diff] [blame] | 66 | #include "ui/gl/gl_image_shared_memory.h" |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 67 | #include "ui/gl/gl_share_group.h" |
Khushal | db2d4ad7 | 2018-07-03 22:36:27 | [diff] [blame^] | 68 | #include "ui/gl/gl_version_info.h" |
| 69 | #include "ui/gl/init/create_gr_gl_interface.h" |
kylechar | 5b9dec1 | 2016-05-16 15:40:57 | [diff] [blame] | 70 | #include "ui/gl/init/gl_factory.h" |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 71 | |
reveman | 27a01ff | 2014-12-20 00:19:00 | [diff] [blame] | 72 | #if defined(OS_WIN) |
| 73 | #include <windows.h> |
| 74 | #include "base/process/process_handle.h" |
| 75 | #endif |
| 76 | |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 77 | namespace gpu { |
| 78 | |
| 79 | namespace { |
| 80 | |
tzik | 184a75bc | 2017-07-13 05:07:41 | [diff] [blame] | 81 | base::AtomicSequenceNumber g_next_command_buffer_id; |
kylechar | 8eebde30 | 2017-08-22 21:50:39 | [diff] [blame] | 82 | base::AtomicSequenceNumber g_next_image_id; |
dyen | 12e4596 | 2015-09-18 00:13:51 | [diff] [blame] | 83 | |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 84 | template <typename T> |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 85 | base::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] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 94 | } |
| 95 | |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 96 | class GpuInProcessThreadHolder : public base::Thread { |
| 97 | public: |
| 98 | GpuInProcessThreadHolder() |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 99 | : base::Thread("GpuThread"), |
| 100 | sync_point_manager_(std::make_unique<SyncPointManager>()) { |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 101 | Start(); |
dyen | ac45ecf | 2015-11-06 17:40:56 | [diff] [blame] | 102 | } |
| 103 | |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 104 | ~GpuInProcessThreadHolder() override { Stop(); } |
| 105 | |
Zhenyao Mo | 56b32be | 2017-08-25 22:59:30 | [diff] [blame] | 106 | void SetGpuFeatureInfo(const GpuFeatureInfo& gpu_feature_info) { |
| 107 | DCHECK(!gpu_thread_service_.get()); |
| 108 | gpu_feature_info_ = gpu_feature_info; |
| 109 | } |
| 110 | |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 111 | scoped_refptr<CommandBufferTaskExecutor> GetGpuThreadService() { |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 112 | if (!gpu_thread_service_) { |
Jonathan Backer | 7bc4459 | 2018-04-25 19:59:50 | [diff] [blame] | 113 | DCHECK(base::CommandLine::InitializedForCurrentProcess()); |
| 114 | const base::CommandLine* command_line = |
| 115 | base::CommandLine::ForCurrentProcess(); |
Jonathan Backer | 76dfd50 | 2018-05-03 18:34:31 | [diff] [blame] | 116 | GpuPreferences gpu_preferences = gles2::ParseGpuPreferences(command_line); |
| 117 | gpu_preferences.texture_target_exception_list = |
| 118 | CreateBufferUsageAndFormatExceptionList(); |
kylechar | 47df630 | 2018-02-14 01:45:48 | [diff] [blame] | 119 | gpu_thread_service_ = base::MakeRefCounted<GpuInProcessThreadService>( |
Jonathan Backer | f277692 | 2018-04-25 18:31:26 | [diff] [blame] | 120 | task_runner(), sync_point_manager_.get(), nullptr, nullptr, |
Jonathan Backer | 76dfd50 | 2018-05-03 18:34:31 | [diff] [blame] | 121 | gpu_feature_info_, gpu_preferences); |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 122 | } |
| 123 | return gpu_thread_service_; |
dyen | ac45ecf | 2015-11-06 17:40:56 | [diff] [blame] | 124 | } |
| 125 | |
| 126 | private: |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 127 | std::unique_ptr<SyncPointManager> sync_point_manager_; |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 128 | scoped_refptr<CommandBufferTaskExecutor> gpu_thread_service_; |
Zhenyao Mo | 56b32be | 2017-08-25 22:59:30 | [diff] [blame] | 129 | GpuFeatureInfo gpu_feature_info_; |
boliu | 23adcfd | 2014-11-27 17:45:53 | [diff] [blame] | 130 | }; |
| 131 | |
scottmg | 5e65e3a | 2017-03-08 08:48:46 | [diff] [blame] | 132 | base::LazyInstance<GpuInProcessThreadHolder>::DestructorAtExit |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 133 | g_default_task_executer = LAZY_INSTANCE_INITIALIZER; |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 134 | |
| 135 | class ScopedEvent { |
| 136 | public: |
dcastagna | 504d45c | 2015-04-06 19:30:39 | [diff] [blame] | 137 | explicit ScopedEvent(base::WaitableEvent* event) : event_(event) {} |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 138 | ~ScopedEvent() { event_->Signal(); } |
| 139 | |
| 140 | private: |
| 141 | base::WaitableEvent* event_; |
| 142 | }; |
| 143 | |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 144 | // If |task_executer| is passed in then it will be returned, otherwise a default |
| 145 | // task_executer will be constructed and returned. |
| 146 | scoped_refptr<CommandBufferTaskExecutor> MaybeGetDefaultTaskExecutor( |
| 147 | scoped_refptr<CommandBufferTaskExecutor> task_executer) { |
| 148 | if (task_executer) |
| 149 | return task_executer; |
hendrikw | 5c1da6d | 2015-06-18 15:08:57 | [diff] [blame] | 150 | |
| 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(); |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 158 | return g_default_task_executer.Get().GetGpuThreadService(); |
hendrikw | 5c1da6d | 2015-06-18 15:08:57 | [diff] [blame] | 159 | } |
| 160 | |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 161 | } // anonyous namespace |
| 162 | |
Sadrul Habib Chowdhury | 7102df0b | 2018-05-30 03:04:17 | [diff] [blame] | 163 | const int InProcessCommandBuffer::kGpuClientId = |
| 164 | std::numeric_limits<int>::max(); |
Christopher Cameron | 9656d1f | 2018-01-28 09:23:19 | [diff] [blame] | 165 | |
[email protected] | aeb316d | 2014-02-13 14:25:25 | [diff] [blame] | 166 | InProcessCommandBuffer::InProcessCommandBuffer( |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 167 | scoped_refptr<CommandBufferTaskExecutor> task_executer) |
sunnyps | c8cc93e27 | 2017-03-21 20:52:27 | [diff] [blame] | 168 | : command_buffer_id_(CommandBufferId::FromUnsafeValue( |
| 169 | g_next_command_buffer_id.GetNext() + 1)), |
gab | ca50ffb | 2016-06-01 23:59:04 | [diff] [blame] | 170 | flush_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC, |
| 171 | base::WaitableEvent::InitialState::NOT_SIGNALED), |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 172 | task_executor_(MaybeGetDefaultTaskExecutor(std::move(task_executer))), |
gab | ca50ffb | 2016-06-01 23:59:04 | [diff] [blame] | 173 | fence_sync_wait_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC, |
| 174 | base::WaitableEvent::InitialState::NOT_SIGNALED), |
danakj | 1005777 | 2016-04-12 19:35:44 | [diff] [blame] | 175 | client_thread_weak_ptr_factory_(this), |
[email protected] | aeb316d | 2014-02-13 14:25:25 | [diff] [blame] | 176 | gpu_thread_weak_ptr_factory_(this) { |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 177 | DCHECK(task_executor_.get()); |
[email protected] | aeb316d | 2014-02-13 14:25:25 | [diff] [blame] | 178 | } |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 179 | |
| 180 | InProcessCommandBuffer::~InProcessCommandBuffer() { |
| 181 | Destroy(); |
| 182 | } |
| 183 | |
Zhenyao Mo | 56b32be | 2017-08-25 22:59:30 | [diff] [blame] | 184 | // static |
| 185 | void 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(); |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 194 | g_default_task_executer.Get().SetGpuFeatureInfo(gpu_feature_info); |
Zhenyao Mo | 56b32be | 2017-08-25 22:59:30 | [diff] [blame] | 195 | } |
| 196 | |
Jonathan Backer | 862b08d | 2018-05-10 15:37:04 | [diff] [blame] | 197 | gpu::ServiceTransferCache* InProcessCommandBuffer::GetTransferCacheForTest() |
| 198 | const { |
| 199 | return static_cast<raster::RasterDecoder*>(decoder_.get()) |
| 200 | ->GetTransferCacheForTest(); |
| 201 | } |
| 202 | |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 203 | bool InProcessCommandBuffer::MakeCurrent() { |
[email protected] | 6172484 | 2013-08-07 09:46:09 | [diff] [blame] | 204 | CheckSequencedThread(); |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 205 | command_buffer_lock_.AssertAcquired(); |
| 206 | |
Antoine Labour | e7e2da6 | 2017-05-25 00:28:26 | [diff] [blame] | 207 | if (error::IsError(command_buffer_->GetState().error)) { |
danakj | 0792522 | 2016-04-07 21:19:27 | [diff] [blame] | 208 | DLOG(ERROR) << "MakeCurrent failed because context lost."; |
| 209 | return false; |
| 210 | } |
| 211 | if (!decoder_->MakeCurrent()) { |
| 212 | DLOG(ERROR) << "Context lost because MakeCurrent failed."; |
Chandan Padhi | 07f05c0 | 2017-09-19 02:52:53 | [diff] [blame] | 213 | command_buffer_->SetParseError(error::kLostContext); |
danakj | 0792522 | 2016-04-07 21:19:27 | [diff] [blame] | 214 | return false; |
| 215 | } |
| 216 | return true; |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 217 | } |
| 218 | |
danakj | 45cfd23 | 2017-10-18 19:31:31 | [diff] [blame] | 219 | gpu::ContextResult InProcessCommandBuffer::Initialize( |
kylechar | 7a46384 | 2016-05-26 14:46:12 | [diff] [blame] | 220 | scoped_refptr<gl::GLSurface> surface, |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 221 | bool is_offscreen, |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 222 | SurfaceHandle window, |
Antoine Labour | feab239 | 2017-12-21 20:28:39 | [diff] [blame] | 223 | const ContextCreationAttribs& attribs, |
reveman | 2232bce | 2014-10-29 01:28:05 | [diff] [blame] | 224 | InProcessCommandBuffer* share_group, |
| 225 | GpuMemoryBufferManager* gpu_memory_buffer_manager, |
ericrk | d989e6a | 2016-09-19 21:17:04 | [diff] [blame] | 226 | ImageFactory* image_factory, |
kylechar | 8e7c5e4d | 2017-12-04 23:43:17 | [diff] [blame] | 227 | GpuChannelManagerDelegate* gpu_channel_manager_delegate, |
ericrk | d989e6a | 2016-09-19 21:17:04 | [diff] [blame] | 228 | scoped_refptr<base::SingleThreadTaskRunner> task_runner) { |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 229 | DCHECK(!share_group || |
| 230 | task_executor_.get() == share_group->task_executor_.get()); |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 231 | |
kylechar | 8e7c5e4d | 2017-12-04 23:43:17 | [diff] [blame] | 232 | gpu_memory_buffer_manager_ = gpu_memory_buffer_manager; |
| 233 | gpu_channel_manager_delegate_ = gpu_channel_manager_delegate; |
| 234 | |
danakj | 1005777 | 2016-04-12 19:35:44 | [diff] [blame] | 235 | if (surface) { |
ericrk | d989e6a | 2016-09-19 21:17:04 | [diff] [blame] | 236 | // 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] | 6172484 | 2013-08-07 09:46:09 | [diff] [blame] | 240 | // 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; |
danakj | 1005777 | 2016-04-12 19:35:44 | [diff] [blame] | 244 | } else { |
ericrk | d989e6a | 2016-09-19 21:17:04 | [diff] [blame] | 245 | DCHECK(task_runner); |
| 246 | origin_task_runner_ = std::move(task_runner); |
danakj | 1005777 | 2016-04-12 19:35:44 | [diff] [blame] | 247 | client_thread_weak_ptr_ = client_thread_weak_ptr_factory_.GetWeakPtr(); |
[email protected] | 6172484 | 2013-08-07 09:46:09 | [diff] [blame] | 248 | } |
| 249 | |
Chandan Padhi | 07f05c0 | 2017-09-19 02:52:53 | [diff] [blame] | 250 | Capabilities capabilities; |
piman | d488e8b4 | 2016-06-30 19:06:59 | [diff] [blame] | 251 | InitializeOnGpuThreadParams params(is_offscreen, window, attribs, |
| 252 | &capabilities, share_group, image_factory); |
[email protected] | 6d66889 | 2013-12-04 21:37:12 | [diff] [blame] | 253 | |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 254 | base::OnceCallback<gpu::ContextResult(void)> init_task = |
| 255 | base::BindOnce(&InProcessCommandBuffer::InitializeOnGpuThread, |
| 256 | base::Unretained(this), params); |
[email protected] | 6172484 | 2013-08-07 09:46:09 | [diff] [blame] | 257 | |
gab | ca50ffb | 2016-06-01 23:59:04 | [diff] [blame] | 258 | base::WaitableEvent completion( |
| 259 | base::WaitableEvent::ResetPolicy::MANUAL, |
| 260 | base::WaitableEvent::InitialState::NOT_SIGNALED); |
danakj | 45cfd23 | 2017-10-18 19:31:31 | [diff] [blame] | 261 | gpu::ContextResult result = gpu::ContextResult::kSuccess; |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 262 | QueueOnceTask(true, |
| 263 | WrapTaskWithResult(std::move(init_task), &result, &completion)); |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 264 | completion.Wait(); |
[email protected] | 6d66889 | 2013-12-04 21:37:12 | [diff] [blame] | 265 | |
danakj | 45cfd23 | 2017-10-18 19:31:31 | [diff] [blame] | 266 | if (result == gpu::ContextResult::kSuccess) |
[email protected] | 6d66889 | 2013-12-04 21:37:12 | [diff] [blame] | 267 | capabilities_ = capabilities; |
reveman | ec103f0 | 2014-09-29 19:12:31 | [diff] [blame] | 268 | |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 269 | return result; |
| 270 | } |
| 271 | |
danakj | 45cfd23 | 2017-10-18 19:31:31 | [diff] [blame] | 272 | gpu::ContextResult InProcessCommandBuffer::InitializeOnGpuThread( |
[email protected] | 6d66889 | 2013-12-04 21:37:12 | [diff] [blame] | 273 | const InitializeOnGpuThreadParams& params) { |
[email protected] | 6172484 | 2013-08-07 09:46:09 | [diff] [blame] | 274 | CheckSequencedThread(); |
[email protected] | 3f0855c0 | 2013-10-09 07:56:25 | [diff] [blame] | 275 | gpu_thread_weak_ptr_ = gpu_thread_weak_ptr_factory_.GetWeakPtr(); |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 276 | |
kylechar | 22b5641 | 2018-04-13 15:58:21 | [diff] [blame] | 277 | // TODO(crbug.com/832243): This could use the TransferBufferManager owned by |
| 278 | // |context_group_| instead. |
Jeremy Roman | 5c453329 | 2017-10-16 23:13:54 | [diff] [blame] | 279 | transfer_buffer_manager_ = std::make_unique<TransferBufferManager>(nullptr); |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 280 | |
Khushal | db2d4ad7 | 2018-07-03 22:36:27 | [diff] [blame^] | 281 | GpuDriverBugWorkarounds workarounds( |
| 282 | task_executor_->gpu_feature_info().enabled_gpu_driver_bug_workarounds); |
kylechar | 22b5641 | 2018-04-13 15:58:21 | [diff] [blame] | 283 | if (params.share_command_buffer) { |
| 284 | context_group_ = params.share_command_buffer->context_group_; |
| 285 | } else { |
Jonathan Backer | a57031b | 2018-06-04 15:44:32 | [diff] [blame] | 286 | auto feature_info = base::MakeRefCounted<gles2::FeatureInfo>( |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 287 | workarounds, task_executor_->gpu_feature_info()); |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 288 | |
kylechar | 22b5641 | 2018-04-13 15:58:21 | [diff] [blame] | 289 | context_group_ = base::MakeRefCounted<gles2::ContextGroup>( |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 290 | task_executor_->gpu_preferences(), |
kylechar | 22b5641 | 2018-04-13 15:58:21 | [diff] [blame] | 291 | gles2::PassthroughCommandDecoderSupported(), |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 292 | 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 Backer | 76dfd50 | 2018-05-03 18:34:31 | [diff] [blame] | 296 | params.image_factory, nullptr /* progress_reporter */, |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 297 | task_executor_->gpu_feature_info(), |
| 298 | task_executor_->discardable_manager()); |
kylechar | 22b5641 | 2018-04-13 15:58:21 | [diff] [blame] | 299 | } |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 300 | |
kylechar | 22b5641 | 2018-04-13 15:58:21 | [diff] [blame] | 301 | #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 | |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 308 | use_virtualized_gl_context_ |= task_executor_->ForceVirtualizedGLContexts(); |
kylechar | 22b5641 | 2018-04-13 15:58:21 | [diff] [blame] | 309 | |
| 310 | // MailboxManagerSync synchronization correctness currently depends on having |
| 311 | // only a single context. See https://crbug.com/510243 for details. |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 312 | use_virtualized_gl_context_ |= task_executor_->mailbox_manager()->UsesSync(); |
kylechar | 22b5641 | 2018-04-13 15:58:21 | [diff] [blame] | 313 | |
| 314 | use_virtualized_gl_context_ |= |
| 315 | context_group_->feature_info()->workarounds().use_virtualized_gl_contexts; |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 316 | |
Jeremy Roman | 5c453329 | 2017-10-16 23:13:54 | [diff] [blame] | 317 | command_buffer_ = std::make_unique<CommandBufferService>( |
Antoine Labour | 1bec107 | 2017-06-06 19:37:03 | [diff] [blame] | 318 | this, transfer_buffer_manager_.get()); |
Jonathan Backer | 0cd1c432 | 2018-04-17 16:57:10 | [diff] [blame] | 319 | |
danakj | 45cfd23 | 2017-10-18 19:31:31 | [diff] [blame] | 320 | if (!surface_) { |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 321 | if (params.is_offscreen) { |
kylechar | 22b5641 | 2018-04-13 15:58:21 | [diff] [blame] | 322 | // TODO(crbug.com/832243): GLES2CommandBufferStub has additional logic for |
| 323 | // offscreen surfaces that might be needed here. |
piman | d488e8b4 | 2016-06-30 19:06:59 | [diff] [blame] | 324 | surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size()); |
kylechar | 22b5641 | 2018-04-13 15:58:21 | [diff] [blame] | 325 | if (!surface_.get()) { |
| 326 | DestroyOnGpuThread(); |
| 327 | LOG(ERROR) << "ContextResult::kFatalFailure: Failed to create surface."; |
danakj | 45cfd23 | 2017-10-18 19:31:31 | [diff] [blame] | 328 | return gpu::ContextResult::kFatalFailure; |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 329 | } |
kylechar | 22b5641 | 2018-04-13 15:58:21 | [diff] [blame] | 330 | } 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(); |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 356 | } |
[email protected] | 6172484 | 2013-08-07 09:46:09 | [diff] [blame] | 357 | } |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 358 | |
kylechar | 22b5641 | 2018-04-13 15:58:21 | [diff] [blame] | 359 | // TODO(crbug.com/832243): InProcessCommandBuffer should support using the GPU |
| 360 | // scheduler for non-WebView cases. |
sunnyps | c8cc93e27 | 2017-03-21 20:52:27 | [diff] [blame] | 361 | sync_point_order_data_ = |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 362 | task_executor_->sync_point_manager()->CreateSyncPointOrderData(); |
sunnyps | c8cc93e27 | 2017-03-21 20:52:27 | [diff] [blame] | 363 | sync_point_client_state_ = |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 364 | task_executor_->sync_point_manager()->CreateSyncPointClientState( |
sunnyps | c8cc93e27 | 2017-03-21 20:52:27 | [diff] [blame] | 365 | GetNamespaceID(), GetCommandBufferID(), |
| 366 | sync_point_order_data_->sequence_id()); |
dyen | a6b0d39a | 2015-09-22 21:53:26 | [diff] [blame] | 367 | |
kylechar | 22b5641 | 2018-04-13 15:58:21 | [diff] [blame] | 368 | 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. |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 379 | gl_share_group_ = task_executor_->share_group(); |
kylechar | 22b5641 | 2018-04-13 15:58:21 | [diff] [blame] | 380 | } |
Sunny Sachanandani | 93c2ec1 | 2017-06-30 03:26:45 | [diff] [blame] | 381 | |
| 382 | // TODO(sunnyps): Should this use ScopedCrashKey instead? |
Robert Sesek | d732922 | 2017-12-08 15:31:08 | [diff] [blame] | 383 | crash_keys::gpu_gl_context_is_virtual.Set(use_virtualized_gl_context_ ? "1" |
| 384 | : "0"); |
Sunny Sachanandani | 93c2ec1 | 2017-06-30 03:26:45 | [diff] [blame] | 385 | |
Khushal | db2d4ad7 | 2018-07-03 22:36:27 | [diff] [blame^] | 386 | // 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] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 404 | } |
Khushal | db2d4ad7 | 2018-07-03 22:36:27 | [diff] [blame^] | 405 | // 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] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 409 | |
Khushal | db2d4ad7 | 2018-07-03 22:36:27 | [diff] [blame^] | 410 | 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_) { |
kylechar | 22b5641 | 2018-04-13 15:58:21 | [diff] [blame] | 444 | 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] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 456 | } |
Khushal | db2d4ad7 | 2018-07-03 22:36:27 | [diff] [blame^] | 457 | |
| 458 | if (!context_->MakeCurrent(surface_.get())) { |
kylechar | 22b5641 | 2018-04-13 15:58:21 | [diff] [blame] | 459 | DestroyOnGpuThread(); |
Khushal | db2d4ad7 | 2018-07-03 22:36:27 | [diff] [blame^] | 460 | // 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 Mo | 56b32be | 2017-08-25 22:59:30 | [diff] [blame] | 464 | } |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 465 | |
kylechar | 22b5641 | 2018-04-13 15:58:21 | [diff] [blame] | 466 | context_->SetGLStateRestorer( |
| 467 | new GLStateRestorerImpl(decoder_->AsWeakPtr())); |
Khushal | db2d4ad7 | 2018-07-03 22:36:27 | [diff] [blame^] | 468 | } else { |
| 469 | context_ = real_context; |
| 470 | DCHECK(context_->IsCurrent(surface_.get())); |
kylechar | 22b5641 | 2018-04-13 15:58:21 | [diff] [blame] | 471 | } |
| 472 | |
| 473 | if (!context_group_->has_program_cache() && |
| 474 | !context_group_->feature_info()->workarounds().disable_program_cache) { |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 475 | context_group_->set_program_cache(task_executor_->program_cache()); |
boliu | a998767 | 2015-08-26 22:51:21 | [diff] [blame] | 476 | } |
| 477 | |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 478 | gles2::DisallowedFeatures disallowed_features; |
danakj | 45cfd23 | 2017-10-18 19:31:31 | [diff] [blame] | 479 | auto result = decoder_->Initialize(surface_, context_, params.is_offscreen, |
| 480 | disallowed_features, params.attribs); |
| 481 | if (result != gpu::ContextResult::kSuccess) { |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 482 | DestroyOnGpuThread(); |
kylechar | 22b5641 | 2018-04-13 15:58:21 | [diff] [blame] | 483 | DLOG(ERROR) << "Failed to initialize decoder."; |
danakj | 45cfd23 | 2017-10-18 19:31:31 | [diff] [blame] | 484 | return result; |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 485 | } |
kylechar | 22b5641 | 2018-04-13 15:58:21 | [diff] [blame] | 486 | |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 487 | if (task_executor_->gpu_preferences().enable_gpu_service_logging) |
Jonathan Backer | 0cd1c432 | 2018-04-17 16:57:10 | [diff] [blame] | 488 | decoder_->SetLogCommands(true); |
kylechar | 22b5641 | 2018-04-13 15:58:21 | [diff] [blame] | 489 | |
| 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] | 01952a6 | 2014-05-02 05:22:01 | [diff] [blame] | 505 | *params.capabilities = decoder_->GetCapabilities(); |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 506 | |
reveman | 2232bce | 2014-10-29 01:28:05 | [diff] [blame] | 507 | image_factory_ = params.image_factory; |
reveman | 2232bce | 2014-10-29 01:28:05 | [diff] [blame] | 508 | |
danakj | 45cfd23 | 2017-10-18 19:31:31 | [diff] [blame] | 509 | return gpu::ContextResult::kSuccess; |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 510 | } |
| 511 | |
| 512 | void InProcessCommandBuffer::Destroy() { |
[email protected] | 6172484 | 2013-08-07 09:46:09 | [diff] [blame] | 513 | CheckSequencedThread(); |
danakj | 1005777 | 2016-04-12 19:35:44 | [diff] [blame] | 514 | client_thread_weak_ptr_factory_.InvalidateWeakPtrs(); |
| 515 | gpu_control_client_ = nullptr; |
gab | ca50ffb | 2016-06-01 23:59:04 | [diff] [blame] | 516 | base::WaitableEvent completion( |
| 517 | base::WaitableEvent::ResetPolicy::MANUAL, |
| 518 | base::WaitableEvent::InitialState::NOT_SIGNALED); |
[email protected] | caa43eb | 2013-08-03 01:52:28 | [diff] [blame] | 519 | bool result = false; |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 520 | base::OnceCallback<bool(void)> destroy_task = base::BindOnce( |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 521 | &InProcessCommandBuffer::DestroyOnGpuThread, base::Unretained(this)); |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 522 | QueueOnceTask( |
| 523 | true, WrapTaskWithResult(std::move(destroy_task), &result, &completion)); |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 524 | completion.Wait(); |
| 525 | } |
| 526 | |
| 527 | bool InProcessCommandBuffer::DestroyOnGpuThread() { |
[email protected] | 6172484 | 2013-08-07 09:46:09 | [diff] [blame] | 528 | CheckSequencedThread(); |
Sunny Sachanandani | 6cec3943 | 2017-07-06 17:33:29 | [diff] [blame] | 529 | // TODO(sunnyps): Should this use ScopedCrashKey instead? |
Robert Sesek | d732922 | 2017-12-08 15:31:08 | [diff] [blame] | 530 | crash_keys::gpu_gl_context_is_virtual.Set(use_virtualized_gl_context_ ? "1" |
| 531 | : "0"); |
[email protected] | 3f0855c0 | 2013-10-09 07:56:25 | [diff] [blame] | 532 | gpu_thread_weak_ptr_factory_.InvalidateWeakPtrs(); |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 533 | // Clean up GL resources if possible. |
Daniel Cheng | 3d7ce9f | 2014-08-26 00:26:25 | [diff] [blame] | 534 | bool have_context = context_.get() && context_->MakeCurrent(surface_.get()); |
Christopher Cameron | 78ad7b11 | 2018-05-09 18:25:01 | [diff] [blame] | 535 | |
| 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] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 541 | if (decoder_) { |
| 542 | decoder_->Destroy(have_context); |
| 543 | decoder_.reset(); |
| 544 | } |
Antoine Labour | 1bec107 | 2017-06-06 19:37:03 | [diff] [blame] | 545 | command_buffer_.reset(); |
danakj | 1005777 | 2016-04-12 19:35:44 | [diff] [blame] | 546 | surface_ = nullptr; |
Christopher Cameron | 3505eac | 2018-02-22 10:00:24 | [diff] [blame] | 547 | |
| 548 | context_ = nullptr; |
dyen | 5c38a03 | 2015-10-07 18:58:31 | [diff] [blame] | 549 | if (sync_point_order_data_) { |
| 550 | sync_point_order_data_->Destroy(); |
| 551 | sync_point_order_data_ = nullptr; |
| 552 | } |
sunnyps | c8cc93e27 | 2017-03-21 20:52:27 | [diff] [blame] | 553 | if (sync_point_client_state_) { |
| 554 | sync_point_client_state_->Destroy(); |
| 555 | sync_point_client_state_ = nullptr; |
| 556 | } |
danakj | 1005777 | 2016-04-12 19:35:44 | [diff] [blame] | 557 | gl_share_group_ = nullptr; |
tzik | 684418e | 2017-02-15 05:48:29 | [diff] [blame] | 558 | context_group_ = nullptr; |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 559 | |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 560 | base::AutoLock lock(task_queue_lock_); |
Brett Wilson | a62d9c0 | 2017-09-20 20:53:20 | [diff] [blame] | 561 | base::queue<std::unique_ptr<GpuTask>> empty; |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 562 | task_queue_.swap(empty); |
| 563 | |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 564 | return true; |
| 565 | } |
| 566 | |
[email protected] | 6172484 | 2013-08-07 09:46:09 | [diff] [blame] | 567 | void InProcessCommandBuffer::CheckSequencedThread() { |
fdoray | e2b19a1 | 2016-07-29 02:30:16 | [diff] [blame] | 568 | DCHECK(!sequence_checker_ || sequence_checker_->CalledOnValidSequence()); |
[email protected] | 6172484 | 2013-08-07 09:46:09 | [diff] [blame] | 569 | } |
| 570 | |
Antoine Labour | 293e93e | 2017-05-26 18:19:11 | [diff] [blame] | 571 | CommandBufferServiceClient::CommandBatchProcessedResult |
| 572 | InProcessCommandBuffer::OnCommandBatchProcessed() { |
| 573 | return kContinueExecution; |
| 574 | } |
| 575 | |
| 576 | void InProcessCommandBuffer::OnParseError() { |
danakj | 1005777 | 2016-04-12 19:35:44 | [diff] [blame] | 577 | 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] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 584 | void InProcessCommandBuffer::OnContextLost() { |
[email protected] | 6172484 | 2013-08-07 09:46:09 | [diff] [blame] | 585 | CheckSequencedThread(); |
danakj | 1005777 | 2016-04-12 19:35:44 | [diff] [blame] | 586 | |
| 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] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 595 | } |
| 596 | |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 597 | void InProcessCommandBuffer::QueueOnceTask(bool out_of_order, |
| 598 | base::OnceClosure task) { |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 599 | if (out_of_order) { |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 600 | task_executor_->ScheduleTask(std::move(task)); |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 601 | 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. |
sunnyps | c8cc93e27 | 2017-03-21 20:52:27 | [diff] [blame] | 605 | uint32_t order_num = sync_point_order_data_->GenerateUnprocessedOrderNumber(); |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 606 | { |
| 607 | base::AutoLock lock(task_queue_lock_); |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 608 | 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 | } |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 612 | task_executor_->ScheduleTask(base::BindOnce( |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 613 | &InProcessCommandBuffer::ProcessTasksOnGpuThread, gpu_thread_weak_ptr_)); |
| 614 | } |
| 615 | |
| 616 | void 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)); |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 625 | } |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 626 | task_executor_->ScheduleTask(base::BindOnce( |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 627 | &InProcessCommandBuffer::ProcessTasksOnGpuThread, gpu_thread_weak_ptr_)); |
| 628 | } |
| 629 | |
| 630 | void InProcessCommandBuffer::ProcessTasksOnGpuThread() { |
Sunny Sachanandani | 93c2ec1 | 2017-06-30 03:26:45 | [diff] [blame] | 631 | // TODO(sunnyps): Should this use ScopedCrashKey instead? |
Robert Sesek | d732922 | 2017-12-08 15:31:08 | [diff] [blame] | 632 | crash_keys::gpu_gl_context_is_virtual.Set(use_virtualized_gl_context_ ? "1" |
| 633 | : "0"); |
Antoine Labour | be0c128 | 2017-05-25 23:04:10 | [diff] [blame] | 634 | while (command_buffer_->scheduled()) { |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 635 | base::AutoLock lock(task_queue_lock_); |
| 636 | if (task_queue_.empty()) |
| 637 | break; |
| 638 | GpuTask* task = task_queue_.front().get(); |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 639 | sync_point_order_data_->BeginProcessingOrderNumber(task->order_number()); |
| 640 | task->Run(); |
Antoine Labour | be0c128 | 2017-05-25 23:04:10 | [diff] [blame] | 641 | if (!command_buffer_->scheduled() && |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 642 | !task_executor_->BlockThreadOnWaitSyncToken()) { |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 643 | sync_point_order_data_->PauseProcessingOrderNumber(task->order_number()); |
mfomitchev | 426ea5dd | 2017-04-14 03:03:39 | [diff] [blame] | 644 | // Don't pop the task if it was preempted - it may have been preempted, so |
| 645 | // we need to execute it again later. |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 646 | DCHECK(task->is_repeatable()); |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 647 | return; |
| 648 | } |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 649 | sync_point_order_data_->FinishProcessingOrderNumber(task->order_number()); |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 650 | task_queue_.pop(); |
| 651 | } |
| 652 | } |
| 653 | |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 654 | CommandBuffer::State InProcessCommandBuffer::GetLastState() { |
[email protected] | 6172484 | 2013-08-07 09:46:09 | [diff] [blame] | 655 | CheckSequencedThread(); |
sunnyps | 12856605 | 2016-12-09 21:06:43 | [diff] [blame] | 656 | base::AutoLock lock(last_state_lock_); |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 657 | return last_state_; |
| 658 | } |
| 659 | |
sunnyps | 12856605 | 2016-12-09 21:06:43 | [diff] [blame] | 660 | void InProcessCommandBuffer::UpdateLastStateOnGpuThread() { |
[email protected] | 6172484 | 2013-08-07 09:46:09 | [diff] [blame] | 661 | CheckSequencedThread(); |
sunnyps | 12856605 | 2016-12-09 21:06:43 | [diff] [blame] | 662 | command_buffer_lock_.AssertAcquired(); |
| 663 | base::AutoLock lock(last_state_lock_); |
Antoine Labour | e7e2da6 | 2017-05-25 00:28:26 | [diff] [blame] | 664 | command_buffer_->UpdateState(); |
| 665 | State state = command_buffer_->GetState(); |
sunnyps | 12856605 | 2016-12-09 21:06:43 | [diff] [blame] | 666 | if (state.generation - last_state_.generation < 0x80000000U) |
| 667 | last_state_ = state; |
[email protected] | 63936fca | 2013-08-07 05:18:54 | [diff] [blame] | 668 | } |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 669 | |
Sadrul Habib Chowdhury | 89a1fbde | 2018-06-14 17:00:41 | [diff] [blame] | 670 | void InProcessCommandBuffer::FlushOnGpuThread(int32_t put_offset) { |
[email protected] | 6172484 | 2013-08-07 09:46:09 | [diff] [blame] | 671 | CheckSequencedThread(); |
[email protected] | 63936fca | 2013-08-07 05:18:54 | [diff] [blame] | 672 | ScopedEvent handle_flush(&flush_event_); |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 673 | base::AutoLock lock(command_buffer_lock_); |
dyen | a6b0d39a | 2015-09-22 21:53:26 | [diff] [blame] | 674 | |
Antoine Labour | 689c26a | 2017-05-25 19:15:44 | [diff] [blame] | 675 | if (!MakeCurrent()) |
| 676 | return; |
| 677 | |
Antoine Labour | 1bec107 | 2017-06-06 19:37:03 | [diff] [blame] | 678 | command_buffer_->Flush(put_offset, decoder_.get()); |
sunnyps | 12856605 | 2016-12-09 21:06:43 | [diff] [blame] | 679 | // Update state before signaling the flush event. |
| 680 | UpdateLastStateOnGpuThread(); |
dyen | a6b0d39a | 2015-09-22 21:53:26 | [diff] [blame] | 681 | |
[email protected] | 3f0855c0 | 2013-10-09 07:56:25 | [diff] [blame] | 682 | // If we've processed all pending commands but still have pending queries, |
| 683 | // pump idle work until the query is passed. |
Antoine Labour | e7e2da6 | 2017-05-25 00:28:26 | [diff] [blame] | 684 | if (put_offset == command_buffer_->GetState().get_offset && |
Antoine Labour | 3aaa590f | 2017-05-24 00:34:34 | [diff] [blame] | 685 | (decoder_->HasMoreIdleWork() || decoder_->HasPendingQueries())) { |
reveman | 87580eb | 2015-09-17 21:45:22 | [diff] [blame] | 686 | ScheduleDelayedWorkOnGpuThread(); |
[email protected] | 3f0855c0 | 2013-10-09 07:56:25 | [diff] [blame] | 687 | } |
| 688 | } |
| 689 | |
danakj | 1005777 | 2016-04-12 19:35:44 | [diff] [blame] | 690 | void InProcessCommandBuffer::PerformDelayedWorkOnGpuThread() { |
[email protected] | 3f0855c0 | 2013-10-09 07:56:25 | [diff] [blame] | 691 | CheckSequencedThread(); |
reveman | 87580eb | 2015-09-17 21:45:22 | [diff] [blame] | 692 | delayed_work_pending_ = false; |
[email protected] | 3f0855c0 | 2013-10-09 07:56:25 | [diff] [blame] | 693 | base::AutoLock lock(command_buffer_lock_); |
Sunny Sachanandani | 93c2ec1 | 2017-06-30 03:26:45 | [diff] [blame] | 694 | // TODO(sunnyps): Should this use ScopedCrashKey instead? |
Robert Sesek | d732922 | 2017-12-08 15:31:08 | [diff] [blame] | 695 | crash_keys::gpu_gl_context_is_virtual.Set(use_virtualized_gl_context_ ? "1" |
| 696 | : "0"); |
reveman | 87580eb | 2015-09-17 21:45:22 | [diff] [blame] | 697 | if (MakeCurrent()) { |
Antoine Labour | 3aaa590f | 2017-05-24 00:34:34 | [diff] [blame] | 698 | decoder_->PerformIdleWork(); |
| 699 | decoder_->ProcessPendingQueries(false); |
| 700 | if (decoder_->HasMoreIdleWork() || decoder_->HasPendingQueries()) { |
reveman | 87580eb | 2015-09-17 21:45:22 | [diff] [blame] | 701 | ScheduleDelayedWorkOnGpuThread(); |
| 702 | } |
[email protected] | 3f0855c0 | 2013-10-09 07:56:25 | [diff] [blame] | 703 | } |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 704 | } |
| 705 | |
reveman | 87580eb | 2015-09-17 21:45:22 | [diff] [blame] | 706 | void InProcessCommandBuffer::ScheduleDelayedWorkOnGpuThread() { |
[email protected] | 0d830e6b | 2014-08-08 09:41:41 | [diff] [blame] | 707 | CheckSequencedThread(); |
reveman | 87580eb | 2015-09-17 21:45:22 | [diff] [blame] | 708 | if (delayed_work_pending_) |
[email protected] | 0d830e6b | 2014-08-08 09:41:41 | [diff] [blame] | 709 | return; |
reveman | 87580eb | 2015-09-17 21:45:22 | [diff] [blame] | 710 | delayed_work_pending_ = true; |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 711 | task_executor_->ScheduleDelayedWork( |
danakj | 1005777 | 2016-04-12 19:35:44 | [diff] [blame] | 712 | base::Bind(&InProcessCommandBuffer::PerformDelayedWorkOnGpuThread, |
| 713 | gpu_thread_weak_ptr_)); |
[email protected] | 0d830e6b | 2014-08-08 09:41:41 | [diff] [blame] | 714 | } |
| 715 | |
avi | f15d60a | 2015-12-21 17:06:33 | [diff] [blame] | 716 | void InProcessCommandBuffer::Flush(int32_t put_offset) { |
[email protected] | 6172484 | 2013-08-07 09:46:09 | [diff] [blame] | 717 | CheckSequencedThread(); |
Chandan Padhi | 07f05c0 | 2017-09-19 02:52:53 | [diff] [blame] | 718 | if (GetLastState().error != error::kNoError) |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 719 | return; |
| 720 | |
| 721 | if (last_put_offset_ == put_offset) |
| 722 | return; |
| 723 | |
| 724 | last_put_offset_ = put_offset; |
Sadrul Habib Chowdhury | 89a1fbde | 2018-06-14 17:00:41 | [diff] [blame] | 725 | base::RepeatingClosure task = |
| 726 | base::BindRepeating(&InProcessCommandBuffer::FlushOnGpuThread, |
| 727 | gpu_thread_weak_ptr_, put_offset); |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 728 | QueueRepeatableTask(std::move(task)); |
dyen | 5c38a03 | 2015-10-07 18:58:31 | [diff] [blame] | 729 | |
| 730 | flushed_fence_sync_release_ = next_fence_sync_release_ - 1; |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 731 | } |
| 732 | |
avi | f15d60a | 2015-12-21 17:06:33 | [diff] [blame] | 733 | void InProcessCommandBuffer::OrderingBarrier(int32_t put_offset) { |
vmiura | b700b43 | 2015-02-06 16:42:51 | [diff] [blame] | 734 | Flush(put_offset); |
| 735 | } |
| 736 | |
sunnyps | 12856605 | 2016-12-09 21:06:43 | [diff] [blame] | 737 | CommandBuffer::State InProcessCommandBuffer::WaitForTokenInRange(int32_t start, |
| 738 | int32_t end) { |
[email protected] | 6172484 | 2013-08-07 09:46:09 | [diff] [blame] | 739 | CheckSequencedThread(); |
sunnyps | 12856605 | 2016-12-09 21:06:43 | [diff] [blame] | 740 | State last_state = GetLastState(); |
| 741 | while (!InRange(start, end, last_state.token) && |
Chandan Padhi | 07f05c0 | 2017-09-19 02:52:53 | [diff] [blame] | 742 | last_state.error == error::kNoError) { |
[email protected] | 7fe4198b | 2014-03-18 21:52:36 | [diff] [blame] | 743 | flush_event_.Wait(); |
sunnyps | 12856605 | 2016-12-09 21:06:43 | [diff] [blame] | 744 | last_state = GetLastState(); |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 745 | } |
sunnyps | 12856605 | 2016-12-09 21:06:43 | [diff] [blame] | 746 | return last_state; |
[email protected] | 7fe4198b | 2014-03-18 21:52:36 | [diff] [blame] | 747 | } |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 748 | |
sunnyps | 12856605 | 2016-12-09 21:06:43 | [diff] [blame] | 749 | CommandBuffer::State InProcessCommandBuffer::WaitForGetOffsetInRange( |
Antoine Labour | d346994 | 2017-05-16 21:23:42 | [diff] [blame] | 750 | uint32_t set_get_buffer_count, |
sunnyps | 12856605 | 2016-12-09 21:06:43 | [diff] [blame] | 751 | int32_t start, |
| 752 | int32_t end) { |
[email protected] | 7fe4198b | 2014-03-18 21:52:36 | [diff] [blame] | 753 | CheckSequencedThread(); |
sunnyps | 12856605 | 2016-12-09 21:06:43 | [diff] [blame] | 754 | State last_state = GetLastState(); |
Antoine Labour | d346994 | 2017-05-16 21:23:42 | [diff] [blame] | 755 | while (((set_get_buffer_count != last_state.set_get_buffer_count) || |
| 756 | !InRange(start, end, last_state.get_offset)) && |
Chandan Padhi | 07f05c0 | 2017-09-19 02:52:53 | [diff] [blame] | 757 | last_state.error == error::kNoError) { |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 758 | flush_event_.Wait(); |
sunnyps | 12856605 | 2016-12-09 21:06:43 | [diff] [blame] | 759 | last_state = GetLastState(); |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 760 | } |
sunnyps | 12856605 | 2016-12-09 21:06:43 | [diff] [blame] | 761 | return last_state; |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 762 | } |
| 763 | |
avi | f15d60a | 2015-12-21 17:06:33 | [diff] [blame] | 764 | void InProcessCommandBuffer::SetGetBuffer(int32_t shm_id) { |
[email protected] | 6172484 | 2013-08-07 09:46:09 | [diff] [blame] | 765 | CheckSequencedThread(); |
Chandan Padhi | 07f05c0 | 2017-09-19 02:52:53 | [diff] [blame] | 766 | if (GetLastState().error != error::kNoError) |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 767 | return; |
| 768 | |
gab | ca50ffb | 2016-06-01 23:59:04 | [diff] [blame] | 769 | base::WaitableEvent completion( |
| 770 | base::WaitableEvent::ResetPolicy::MANUAL, |
| 771 | base::WaitableEvent::InitialState::NOT_SIGNALED); |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 772 | base::OnceClosure task = |
| 773 | base::BindOnce(&InProcessCommandBuffer::SetGetBufferOnGpuThread, |
| 774 | base::Unretained(this), shm_id, &completion); |
| 775 | QueueOnceTask(false, std::move(task)); |
vmpstr | d3435c6cd | 2015-06-13 00:31:25 | [diff] [blame] | 776 | completion.Wait(); |
| 777 | |
sunnyps | 12856605 | 2016-12-09 21:06:43 | [diff] [blame] | 778 | last_put_offset_ = 0; |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 779 | } |
| 780 | |
vmpstr | d3435c6cd | 2015-06-13 00:31:25 | [diff] [blame] | 781 | void InProcessCommandBuffer::SetGetBufferOnGpuThread( |
avi | f15d60a | 2015-12-21 17:06:33 | [diff] [blame] | 782 | int32_t shm_id, |
vmpstr | d3435c6cd | 2015-06-13 00:31:25 | [diff] [blame] | 783 | base::WaitableEvent* completion) { |
| 784 | base::AutoLock lock(command_buffer_lock_); |
| 785 | command_buffer_->SetGetBuffer(shm_id); |
sunnyps | 12856605 | 2016-12-09 21:06:43 | [diff] [blame] | 786 | UpdateLastStateOnGpuThread(); |
vmpstr | d3435c6cd | 2015-06-13 00:31:25 | [diff] [blame] | 787 | completion->Signal(); |
| 788 | } |
| 789 | |
avi | f15d60a | 2015-12-21 17:06:33 | [diff] [blame] | 790 | scoped_refptr<Buffer> InProcessCommandBuffer::CreateTransferBuffer( |
| 791 | size_t size, |
| 792 | int32_t* id) { |
[email protected] | 6172484 | 2013-08-07 09:46:09 | [diff] [blame] | 793 | CheckSequencedThread(); |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 794 | base::AutoLock lock(command_buffer_lock_); |
| 795 | return command_buffer_->CreateTransferBuffer(size, id); |
| 796 | } |
| 797 | |
avi | f15d60a | 2015-12-21 17:06:33 | [diff] [blame] | 798 | void InProcessCommandBuffer::DestroyTransferBuffer(int32_t id) { |
[email protected] | 6172484 | 2013-08-07 09:46:09 | [diff] [blame] | 799 | CheckSequencedThread(); |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 800 | base::OnceClosure task = |
| 801 | base::BindOnce(&InProcessCommandBuffer::DestroyTransferBufferOnGpuThread, |
| 802 | base::Unretained(this), id); |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 803 | |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 804 | QueueOnceTask(false, std::move(task)); |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 805 | } |
| 806 | |
avi | f15d60a | 2015-12-21 17:06:33 | [diff] [blame] | 807 | void InProcessCommandBuffer::DestroyTransferBufferOnGpuThread(int32_t id) { |
[email protected] | 02f1e6a | 2014-04-11 21:08:36 | [diff] [blame] | 808 | base::AutoLock lock(command_buffer_lock_); |
| 809 | command_buffer_->DestroyTransferBuffer(id); |
| 810 | } |
| 811 | |
danakj | 1005777 | 2016-04-12 19:35:44 | [diff] [blame] | 812 | void InProcessCommandBuffer::SetGpuControlClient(GpuControlClient* client) { |
| 813 | gpu_control_client_ = client; |
| 814 | } |
| 815 | |
Zhenyao Mo | eb86a171 | 2017-10-06 14:17:52 | [diff] [blame] | 816 | const Capabilities& InProcessCommandBuffer::GetCapabilities() const { |
[email protected] | 6d66889 | 2013-12-04 21:37:12 | [diff] [blame] | 817 | return capabilities_; |
[email protected] | 744e079 | 2013-09-27 01:18:35 | [diff] [blame] | 818 | } |
| 819 | |
Zhenyao Mo | 04ea0f0 | 2017-10-12 01:15:54 | [diff] [blame] | 820 | const GpuFeatureInfo& InProcessCommandBuffer::GetGpuFeatureInfo() const { |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 821 | return task_executor_->gpu_feature_info(); |
Zhenyao Mo | 04ea0f0 | 2017-10-12 01:15:54 | [diff] [blame] | 822 | } |
| 823 | |
avi | f15d60a | 2015-12-21 17:06:33 | [diff] [blame] | 824 | int32_t InProcessCommandBuffer::CreateImage(ClientBuffer buffer, |
| 825 | size_t width, |
| 826 | size_t height, |
| 827 | unsigned internalformat) { |
reveman | 2232bce | 2014-10-29 01:28:05 | [diff] [blame] | 828 | CheckSequencedThread(); |
| 829 | |
| 830 | DCHECK(gpu_memory_buffer_manager_); |
| 831 | gfx::GpuMemoryBuffer* gpu_memory_buffer = |
sadrul | 849cb9e | 2016-11-09 17:19:45 | [diff] [blame] | 832 | reinterpret_cast<gfx::GpuMemoryBuffer*>(buffer); |
reveman | 2232bce | 2014-10-29 01:28:05 | [diff] [blame] | 833 | DCHECK(gpu_memory_buffer); |
| 834 | |
kylechar | 8eebde30 | 2017-08-22 21:50:39 | [diff] [blame] | 835 | int32_t new_id = g_next_image_id.GetNext() + 1; |
reveman | 2232bce | 2014-10-29 01:28:05 | [diff] [blame] | 836 | |
Chandan Padhi | 07f05c0 | 2017-09-19 02:52:53 | [diff] [blame] | 837 | DCHECK(IsImageFromGpuMemoryBufferFormatSupported( |
ccameron | c1fcde5 | 2017-04-12 19:40:49 | [diff] [blame] | 838 | gpu_memory_buffer->GetFormat(), capabilities_)); |
Chandan Padhi | 07f05c0 | 2017-09-19 02:52:53 | [diff] [blame] | 839 | DCHECK(IsImageFormatCompatibleWithGpuMemoryBufferFormat( |
reveman | 2232bce | 2014-10-29 01:28:05 | [diff] [blame] | 840 | internalformat, gpu_memory_buffer->GetFormat())); |
reveman | 27a01ff | 2014-12-20 00:19:00 | [diff] [blame] | 841 | |
| 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. |
sadrul | 73794ca | 2016-11-29 04:10:07 | [diff] [blame] | 845 | gfx::GpuMemoryBufferHandle handle = |
| 846 | gfx::CloneHandleForIPC(gpu_memory_buffer->GetHandle()); |
| 847 | bool requires_sync_point = handle.type == gfx::IO_SURFACE_BUFFER; |
reveman | 27a01ff | 2014-12-20 00:19:00 | [diff] [blame] | 848 | |
dyen | ac45ecf | 2015-11-06 17:40:56 | [diff] [blame] | 849 | uint64_t fence_sync = 0; |
nhiroki | a1ab22a | 2015-11-05 05:56:05 | [diff] [blame] | 850 | if (requires_sync_point) { |
dyen | ac45ecf | 2015-11-06 17:40:56 | [diff] [blame] | 851 | 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 Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 857 | QueueOnceTask( |
| 858 | false, |
| 859 | base::BindOnce(&InProcessCommandBuffer::CreateImageOnGpuThread, |
Alexandr Ilin | d82fcd8 | 2018-06-25 17:47:38 | [diff] [blame] | 860 | base::Unretained(this), new_id, std::move(handle), |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 861 | 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)); |
dyen | ac45ecf | 2015-11-06 17:40:56 | [diff] [blame] | 865 | |
| 866 | if (fence_sync) { |
| 867 | flushed_fence_sync_release_ = fence_sync; |
Sunny Sachanandani | db1759e | 2017-12-20 22:33:21 | [diff] [blame] | 868 | SyncToken sync_token(GetNamespaceID(), GetCommandBufferID(), fence_sync); |
dyen | ac45ecf | 2015-11-06 17:40:56 | [diff] [blame] | 869 | sync_token.SetVerifyFlush(); |
| 870 | gpu_memory_buffer_manager_->SetDestructionSyncToken(gpu_memory_buffer, |
| 871 | sync_token); |
reveman | 27a01ff | 2014-12-20 00:19:00 | [diff] [blame] | 872 | } |
| 873 | |
reveman | 2232bce | 2014-10-29 01:28:05 | [diff] [blame] | 874 | return new_id; |
| 875 | } |
| 876 | |
| 877 | void InProcessCommandBuffer::CreateImageOnGpuThread( |
avi | f15d60a | 2015-12-21 17:06:33 | [diff] [blame] | 878 | int32_t id, |
Alexandr Ilin | d82fcd8 | 2018-06-25 17:47:38 | [diff] [blame] | 879 | gfx::GpuMemoryBufferHandle handle, |
reveman | 2232bce | 2014-10-29 01:28:05 | [diff] [blame] | 880 | const gfx::Size& size, |
spang | fcf5fab4 | 2015-08-04 19:25:35 | [diff] [blame] | 881 | gfx::BufferFormat format, |
avi | f15d60a | 2015-12-21 17:06:33 | [diff] [blame] | 882 | uint32_t internalformat, |
dyen | ac45ecf | 2015-11-06 17:40:56 | [diff] [blame] | 883 | uint64_t fence_sync) { |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 884 | gles2::ImageManager* image_manager = task_executor_->image_manager(); |
reveman | 2232bce | 2014-10-29 01:28:05 | [diff] [blame] | 885 | DCHECK(image_manager); |
| 886 | if (image_manager->LookupImage(id)) { |
| 887 | LOG(ERROR) << "Image already exists with same ID."; |
| 888 | return; |
| 889 | } |
| 890 | |
reveman | 5f717f8 | 2015-05-21 23:21:07 | [diff] [blame] | 891 | switch (handle.type) { |
| 892 | case gfx::SHARED_MEMORY_BUFFER: { |
reveman | 730fd961 | 2015-11-11 01:22:43 | [diff] [blame] | 893 | if (!base::IsValueInRangeForNumericType<size_t>(handle.stride)) { |
| 894 | LOG(ERROR) << "Invalid stride for image."; |
| 895 | return; |
| 896 | } |
tfarina | df856e02 | 2015-10-29 12:50:45 | [diff] [blame] | 897 | scoped_refptr<gl::GLImageSharedMemory> image( |
| 898 | new gl::GLImageSharedMemory(size, internalformat)); |
reveman | 730fd961 | 2015-11-11 01:22:43 | [diff] [blame] | 899 | if (!image->Initialize(handle.handle, handle.id, format, handle.offset, |
| 900 | handle.stride)) { |
reveman | 5f717f8 | 2015-05-21 23:21:07 | [diff] [blame] | 901 | LOG(ERROR) << "Failed to initialize image."; |
| 902 | return; |
| 903 | } |
reveman | 2232bce | 2014-10-29 01:28:05 | [diff] [blame] | 904 | |
reveman | 5f717f8 | 2015-05-21 23:21:07 | [diff] [blame] | 905 | 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 | } |
reveman | 2232bce | 2014-10-29 01:28:05 | [diff] [blame] | 913 | |
tfarina | df856e02 | 2015-10-29 12:50:45 | [diff] [blame] | 914 | scoped_refptr<gl::GLImage> image = |
reveman | 5f717f8 | 2015-05-21 23:21:07 | [diff] [blame] | 915 | image_factory_->CreateImageForGpuMemoryBuffer( |
Alexandr Ilin | d82fcd8 | 2018-06-25 17:47:38 | [diff] [blame] | 916 | std::move(handle), size, format, internalformat, kGpuClientId, |
reveman | 15e3d9a | 2016-07-19 18:21:12 | [diff] [blame] | 917 | kNullSurfaceHandle); |
reveman | 5f717f8 | 2015-05-21 23:21:07 | [diff] [blame] | 918 | 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 | } |
dyen | ac45ecf | 2015-11-06 17:40:56 | [diff] [blame] | 927 | |
sunnyps | 9147a531 | 2017-03-02 20:26:37 | [diff] [blame] | 928 | if (fence_sync) |
sunnyps | c8cc93e27 | 2017-03-21 20:52:27 | [diff] [blame] | 929 | sync_point_client_state_->ReleaseFenceSync(fence_sync); |
reveman | 22dd929 | 2014-10-13 20:52:05 | [diff] [blame] | 930 | } |
| 931 | |
avi | f15d60a | 2015-12-21 17:06:33 | [diff] [blame] | 932 | void InProcessCommandBuffer::DestroyImage(int32_t id) { |
reveman | 2232bce | 2014-10-29 01:28:05 | [diff] [blame] | 933 | CheckSequencedThread(); |
| 934 | |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 935 | QueueOnceTask(false, |
| 936 | base::BindOnce(&InProcessCommandBuffer::DestroyImageOnGpuThread, |
| 937 | base::Unretained(this), id)); |
reveman | 2232bce | 2014-10-29 01:28:05 | [diff] [blame] | 938 | } |
| 939 | |
avi | f15d60a | 2015-12-21 17:06:33 | [diff] [blame] | 940 | void InProcessCommandBuffer::DestroyImageOnGpuThread(int32_t id) { |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 941 | gles2::ImageManager* image_manager = task_executor_->image_manager(); |
reveman | 2232bce | 2014-10-29 01:28:05 | [diff] [blame] | 942 | 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); |
reveman | 22dd929 | 2014-10-13 20:52:05 | [diff] [blame] | 949 | } |
| 950 | |
Antoine Labour | f679fa4 | 2017-06-07 00:32:43 | [diff] [blame] | 951 | void InProcessCommandBuffer::OnConsoleMessage(int32_t id, |
| 952 | const std::string& message) { |
| 953 | // TODO(piman): implement this. |
| 954 | } |
| 955 | |
| 956 | void InProcessCommandBuffer::CacheShader(const std::string& key, |
| 957 | const std::string& shader) { |
Sadrul Habib Chowdhury | 7102df0b | 2018-05-30 03:04:17 | [diff] [blame] | 958 | if (gpu_channel_manager_delegate_) |
| 959 | gpu_channel_manager_delegate_->StoreShaderToDisk(kGpuClientId, key, shader); |
Antoine Labour | f679fa4 | 2017-06-07 00:32:43 | [diff] [blame] | 960 | } |
| 961 | |
| 962 | void InProcessCommandBuffer::OnFenceSyncRelease(uint64_t release) { |
Sunny Sachanandani | db1759e | 2017-12-20 22:33:21 | [diff] [blame] | 963 | SyncToken sync_token(GetNamespaceID(), GetCommandBufferID(), release); |
sunnyps | 9147a531 | 2017-03-02 20:26:37 | [diff] [blame] | 964 | |
kylechar | 22b5641 | 2018-04-13 15:58:21 | [diff] [blame] | 965 | context_group_->mailbox_manager()->PushTextureUpdates(sync_token); |
dyen | 5c38a03 | 2015-10-07 18:58:31 | [diff] [blame] | 966 | |
sunnyps | c8cc93e27 | 2017-03-21 20:52:27 | [diff] [blame] | 967 | sync_point_client_state_->ReleaseFenceSync(release); |
dyen | 5c38a03 | 2015-10-07 18:58:31 | [diff] [blame] | 968 | } |
| 969 | |
Antoine Labour | f679fa4 | 2017-06-07 00:32:43 | [diff] [blame] | 970 | bool InProcessCommandBuffer::OnWaitSyncToken(const SyncToken& sync_token) { |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 971 | DCHECK(!waiting_for_sync_point_); |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 972 | SyncPointManager* sync_point_manager = task_executor_->sync_point_manager(); |
dyen | 5c38a03 | 2015-10-07 18:58:31 | [diff] [blame] | 973 | DCHECK(sync_point_manager); |
| 974 | |
kylechar | 22b5641 | 2018-04-13 15:58:21 | [diff] [blame] | 975 | MailboxManager* mailbox_manager = context_group_->mailbox_manager(); |
sunnyps | 9147a531 | 2017-03-02 20:26:37 | [diff] [blame] | 976 | DCHECK(mailbox_manager); |
dyen | 5c38a03 | 2015-10-07 18:58:31 | [diff] [blame] | 977 | |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 978 | if (task_executor_->BlockThreadOnWaitSyncToken()) { |
sunnyps | 9147a531 | 2017-03-02 20:26:37 | [diff] [blame] | 979 | // Wait if sync point wait is valid. |
sunnyps | c8cc93e27 | 2017-03-21 20:52:27 | [diff] [blame] | 980 | if (sync_point_client_state_->Wait( |
sunnyps | 9147a531 | 2017-03-02 20:26:37 | [diff] [blame] | 981 | sync_token, |
| 982 | base::Bind(&base::WaitableEvent::Signal, |
| 983 | base::Unretained(&fence_sync_wait_event_)))) { |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 984 | fence_sync_wait_event_.Wait(); |
| 985 | } |
| 986 | |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 987 | mailbox_manager->PullTextureUpdates(sync_token); |
sunnyps | 9147a531 | 2017-03-02 20:26:37 | [diff] [blame] | 988 | return false; |
dyen | 5c38a03 | 2015-10-07 18:58:31 | [diff] [blame] | 989 | } |
| 990 | |
sunnyps | c8cc93e27 | 2017-03-21 20:52:27 | [diff] [blame] | 991 | waiting_for_sync_point_ = sync_point_client_state_->Wait( |
sunnyps | 9147a531 | 2017-03-02 20:26:37 | [diff] [blame] | 992 | sync_token, |
| 993 | base::Bind(&InProcessCommandBuffer::OnWaitSyncTokenCompleted, |
| 994 | gpu_thread_weak_ptr_factory_.GetWeakPtr(), sync_token)); |
| 995 | if (!waiting_for_sync_point_) { |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 996 | mailbox_manager->PullTextureUpdates(sync_token); |
sunnyps | 9147a531 | 2017-03-02 20:26:37 | [diff] [blame] | 997 | return false; |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 998 | } |
| 999 | |
Antoine Labour | be0c128 | 2017-05-25 23:04:10 | [diff] [blame] | 1000 | command_buffer_->SetScheduled(false); |
sunnyps | 9147a531 | 2017-03-02 20:26:37 | [diff] [blame] | 1001 | return true; |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 1002 | } |
| 1003 | |
sunnyps | 9147a531 | 2017-03-02 20:26:37 | [diff] [blame] | 1004 | void InProcessCommandBuffer::OnWaitSyncTokenCompleted( |
| 1005 | const SyncToken& sync_token) { |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 1006 | DCHECK(waiting_for_sync_point_); |
kylechar | 22b5641 | 2018-04-13 15:58:21 | [diff] [blame] | 1007 | context_group_->mailbox_manager()->PullTextureUpdates(sync_token); |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 1008 | waiting_for_sync_point_ = false; |
Antoine Labour | be0c128 | 2017-05-25 23:04:10 | [diff] [blame] | 1009 | command_buffer_->SetScheduled(true); |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 1010 | task_executor_->ScheduleTask(base::BindOnce( |
mfomitchev | 995b74dc | 2017-04-12 22:55:18 | [diff] [blame] | 1011 | &InProcessCommandBuffer::ProcessTasksOnGpuThread, gpu_thread_weak_ptr_)); |
sievers | 173a20d | 2014-10-22 18:19:32 | [diff] [blame] | 1012 | } |
| 1013 | |
Antoine Labour | f679fa4 | 2017-06-07 00:32:43 | [diff] [blame] | 1014 | void InProcessCommandBuffer::OnDescheduleUntilFinished() { |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 1015 | if (!task_executor_->BlockThreadOnWaitSyncToken()) { |
Antoine Labour | be0c128 | 2017-05-25 23:04:10 | [diff] [blame] | 1016 | DCHECK(command_buffer_->scheduled()); |
Antoine Labour | 3aaa590f | 2017-05-24 00:34:34 | [diff] [blame] | 1017 | DCHECK(decoder_->HasPollingWork()); |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 1018 | |
Antoine Labour | be0c128 | 2017-05-25 23:04:10 | [diff] [blame] | 1019 | command_buffer_->SetScheduled(false); |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 1020 | } |
erikchen | 13338b6 | 2016-06-01 03:58:18 | [diff] [blame] | 1021 | } |
| 1022 | |
Antoine Labour | f679fa4 | 2017-06-07 00:32:43 | [diff] [blame] | 1023 | void InProcessCommandBuffer::OnRescheduleAfterFinished() { |
kylechar | 2fdaa04 | 2018-07-03 17:36:23 | [diff] [blame] | 1024 | if (!task_executor_->BlockThreadOnWaitSyncToken()) { |
Antoine Labour | be0c128 | 2017-05-25 23:04:10 | [diff] [blame] | 1025 | DCHECK(!command_buffer_->scheduled()); |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 1026 | |
Antoine Labour | be0c128 | 2017-05-25 23:04:10 | [diff] [blame] | 1027 | command_buffer_->SetScheduled(true); |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 1028 | ProcessTasksOnGpuThread(); |
| 1029 | } |
erikchen | 13338b6 | 2016-06-01 03:58:18 | [diff] [blame] | 1030 | } |
| 1031 | |
Eric Karl | b6b2c63 | 2018-05-07 22:45:04 | [diff] [blame] | 1032 | void InProcessCommandBuffer::OnSwapBuffers(uint64_t swap_id, uint32_t flags) { |
| 1033 | pending_swap_completed_params_.push_back({swap_id, flags}); |
Peng Huang | 606ca80 | 2018-05-18 15:50:02 | [diff] [blame] | 1034 | pending_presented_params_.push_back({swap_id, flags}); |
Eric Karl | b6b2c63 | 2018-05-07 22:45:04 | [diff] [blame] | 1035 | } |
Peng Huang | 2a30e26 | 2018-05-02 21:08:59 | [diff] [blame] | 1036 | |
dyen | ae103dce | 2015-11-17 19:59:04 | [diff] [blame] | 1037 | void InProcessCommandBuffer::SignalSyncTokenOnGpuThread( |
fsamuel | 600b99e | 2016-11-11 07:50:26 | [diff] [blame] | 1038 | const SyncToken& sync_token, |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 1039 | 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 | } |
dyen | ae103dce | 2015-11-17 19:59:04 | [diff] [blame] | 1045 | } |
| 1046 | |
[email protected] | b63f1d6 | 2014-07-18 15:40:59 | [diff] [blame] | 1047 | void InProcessCommandBuffer::SignalQuery(unsigned query_id, |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 1048 | base::OnceClosure callback) { |
[email protected] | 3f0855c0 | 2013-10-09 07:56:25 | [diff] [blame] | 1049 | CheckSequencedThread(); |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 1050 | QueueOnceTask(false, |
| 1051 | base::BindOnce(&InProcessCommandBuffer::SignalQueryOnGpuThread, |
| 1052 | base::Unretained(this), query_id, |
| 1053 | WrapCallback(std::move(callback)))); |
[email protected] | b88a48cc | 2013-10-05 05:10:10 | [diff] [blame] | 1054 | } |
| 1055 | |
[email protected] | b63f1d6 | 2014-07-18 15:40:59 | [diff] [blame] | 1056 | void InProcessCommandBuffer::SignalQueryOnGpuThread( |
| 1057 | unsigned query_id, |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 1058 | base::OnceClosure callback) { |
Geoff Lang | 85287e1 | 2018-05-22 17:26:40 | [diff] [blame] | 1059 | decoder_->SetQueryCallback(query_id, std::move(callback)); |
[email protected] | b63f1d6 | 2014-07-18 15:40:59 | [diff] [blame] | 1060 | } |
| 1061 | |
Klaus Weidner | e66cc7d | 2017-12-09 17:26:30 | [diff] [blame] | 1062 | void 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 Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 1072 | QueueOnceTask( |
| 1073 | false, base::BindOnce(&InProcessCommandBuffer::CreateGpuFenceOnGpuThread, |
| 1074 | base::Unretained(this), gpu_fence_id, handle)); |
Klaus Weidner | e66cc7d | 2017-12-09 17:26:30 | [diff] [blame] | 1075 | } |
| 1076 | |
| 1077 | void 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 | |
| 1097 | void InProcessCommandBuffer::GetGpuFence( |
| 1098 | uint32_t gpu_fence_id, |
| 1099 | base::OnceCallback<void(std::unique_ptr<gfx::GpuFence>)> callback) { |
| 1100 | CheckSequencedThread(); |
Klaus Weidner | e66cc7d | 2017-12-09 17:26:30 | [diff] [blame] | 1101 | auto task_runner = base::ThreadTaskRunnerHandle::IsSet() |
| 1102 | ? base::ThreadTaskRunnerHandle::Get() |
| 1103 | : nullptr; |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 1104 | QueueOnceTask( |
| 1105 | false, base::BindOnce(&InProcessCommandBuffer::GetGpuFenceOnGpuThread, |
| 1106 | base::Unretained(this), gpu_fence_id, task_runner, |
| 1107 | std::move(callback))); |
Klaus Weidner | e66cc7d | 2017-12-09 17:26:30 | [diff] [blame] | 1108 | } |
| 1109 | |
| 1110 | void 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 | |
jbauman | 6875d4e0 | 2015-02-12 00:44:59 | [diff] [blame] | 1144 | void InProcessCommandBuffer::SetLock(base::Lock*) { |
danakj | 0792522 | 2016-04-07 21:19:27 | [diff] [blame] | 1145 | // No support for using on multiple threads. |
| 1146 | NOTREACHED(); |
jbauman | 6875d4e0 | 2015-02-12 00:44:59 | [diff] [blame] | 1147 | } |
| 1148 | |
dyen | 293de3c | 2016-01-05 02:08:05 | [diff] [blame] | 1149 | void InProcessCommandBuffer::EnsureWorkVisible() { |
| 1150 | // This is only relevant for out-of-process command buffers. |
| 1151 | } |
| 1152 | |
dyen | 12e4596 | 2015-09-18 00:13:51 | [diff] [blame] | 1153 | CommandBufferNamespace InProcessCommandBuffer::GetNamespaceID() const { |
| 1154 | return CommandBufferNamespace::IN_PROCESS; |
| 1155 | } |
| 1156 | |
lukasza | 2573ce7d | 2016-02-16 19:17:22 | [diff] [blame] | 1157 | CommandBufferId InProcessCommandBuffer::GetCommandBufferID() const { |
dyen | 12e4596 | 2015-09-18 00:13:51 | [diff] [blame] | 1158 | return command_buffer_id_; |
| 1159 | } |
| 1160 | |
Sunny Sachanandani | 9b8fb34 | 2017-08-26 00:49:56 | [diff] [blame] | 1161 | void InProcessCommandBuffer::FlushPendingWork() { |
Sunny Sachanandani | 5f5419e2 | 2017-05-12 20:35:30 | [diff] [blame] | 1162 | // This is only relevant for out-of-process command buffers. |
| 1163 | } |
| 1164 | |
dyen | 5c38a03 | 2015-10-07 18:58:31 | [diff] [blame] | 1165 | uint64_t InProcessCommandBuffer::GenerateFenceSyncRelease() { |
| 1166 | return next_fence_sync_release_++; |
| 1167 | } |
| 1168 | |
sunnyps | 12856605 | 2016-12-09 21:06:43 | [diff] [blame] | 1169 | bool InProcessCommandBuffer::IsFenceSyncReleased(uint64_t release) { |
| 1170 | return release <= GetLastState().release_count; |
| 1171 | } |
| 1172 | |
dyen | 6f3b439 | 2015-10-22 20:17:23 | [diff] [blame] | 1173 | void InProcessCommandBuffer::SignalSyncToken(const SyncToken& sync_token, |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 1174 | base::OnceClosure callback) { |
dyen | ae103dce | 2015-11-17 19:59:04 | [diff] [blame] | 1175 | CheckSequencedThread(); |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 1176 | QueueOnceTask( |
| 1177 | false, base::BindOnce(&InProcessCommandBuffer::SignalSyncTokenOnGpuThread, |
| 1178 | base::Unretained(this), sync_token, |
| 1179 | WrapCallback(std::move(callback)))); |
dyen | 6f3b439 | 2015-10-22 20:17:23 | [diff] [blame] | 1180 | } |
| 1181 | |
sunnyps | 7499629 | 2017-03-15 02:35:48 | [diff] [blame] | 1182 | void InProcessCommandBuffer::WaitSyncTokenHint(const SyncToken& sync_token) {} |
| 1183 | |
dyen | 55719a1 | 2015-10-14 17:26:11 | [diff] [blame] | 1184 | bool InProcessCommandBuffer::CanWaitUnverifiedSyncToken( |
sunnyps | 7499629 | 2017-03-15 02:35:48 | [diff] [blame] | 1185 | const SyncToken& sync_token) { |
| 1186 | return sync_token.namespace_id() == GetNamespaceID(); |
dyen | 55719a1 | 2015-10-14 17:26:11 | [diff] [blame] | 1187 | } |
| 1188 | |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 1189 | #if defined(OS_WIN) |
| 1190 | void InProcessCommandBuffer::DidCreateAcceleratedSurfaceChildWindow( |
| 1191 | SurfaceHandle parent_window, |
| 1192 | SurfaceHandle child_window) { |
kylechar | 8e7c5e4d | 2017-12-04 23:43:17 | [diff] [blame] | 1193 | // In the browser process call ::SetParent() directly. |
| 1194 | if (!gpu_channel_manager_delegate_) { |
| 1195 | ::SetParent(child_window, parent_window); |
chaopeng | f77fb4f7 | 2018-01-19 20:31:42 | [diff] [blame] | 1196 | // 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); |
kylechar | 8e7c5e4d | 2017-12-04 23:43:17 | [diff] [blame] | 1199 | return; |
| 1200 | } |
| 1201 | |
| 1202 | // In the GPU process forward the request back to the browser process. |
kylechar | cd157cc | 2018-05-30 17:30:02 | [diff] [blame] | 1203 | gpu_channel_manager_delegate_->SendCreatedChildWindow(parent_window, |
| 1204 | child_window); |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 1205 | } |
| 1206 | #endif |
| 1207 | |
| 1208 | void InProcessCommandBuffer::DidSwapBuffersComplete( |
| 1209 | SwapBuffersCompleteParams params) { |
Eric Karl | b6b2c63 | 2018-05-07 22:45:04 | [diff] [blame] | 1210 | params.swap_response.swap_id = pending_swap_completed_params_.front().swap_id; |
| 1211 | pending_swap_completed_params_.pop_front(); |
| 1212 | |
fsamuel | 58b5a22 | 2016-11-23 23:50:24 | [diff] [blame] | 1213 | 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(¶ms))); |
| 1221 | } |
| 1222 | |
| 1223 | const gles2::FeatureInfo* InProcessCommandBuffer::GetFeatureInfo() const { |
| 1224 | return context_group_->feature_info(); |
| 1225 | } |
| 1226 | |
John Bauman | 39210ea | 2017-07-27 23:11:55 | [diff] [blame] | 1227 | const GpuPreferences& InProcessCommandBuffer::GetGpuPreferences() const { |
| 1228 | return context_group_->gpu_preferences(); |
| 1229 | } |
| 1230 | |
Peng Huang | 6bf9277 | 2017-11-30 18:57:08 | [diff] [blame] | 1231 | void InProcessCommandBuffer::BufferPresented( |
Peng Huang | 6bf9277 | 2017-11-30 18:57:08 | [diff] [blame] | 1232 | const gfx::PresentationFeedback& feedback) { |
Jonathan Backer | 57ecd00 | 2018-05-23 13:20:31 | [diff] [blame] | 1233 | SwapBufferParams params = pending_presented_params_.front(); |
Eric Karl | b6b2c63 | 2018-05-07 22:45:04 | [diff] [blame] | 1234 | pending_presented_params_.pop_front(); |
| 1235 | |
Peng Huang | 6bf9277 | 2017-11-30 18:57:08 | [diff] [blame] | 1236 | if (!origin_task_runner_) { |
Eric Karl | b6b2c63 | 2018-05-07 22:45:04 | [diff] [blame] | 1237 | BufferPresentedOnOriginThread(params.swap_id, params.flags, feedback); |
Peng Huang | 6bf9277 | 2017-11-30 18:57:08 | [diff] [blame] | 1238 | return; |
| 1239 | } |
| 1240 | origin_task_runner_->PostTask( |
| 1241 | FROM_HERE, |
| 1242 | base::Bind(&InProcessCommandBuffer::BufferPresentedOnOriginThread, |
Eric Karl | b6b2c63 | 2018-05-07 22:45:04 | [diff] [blame] | 1243 | client_thread_weak_ptr_, params.swap_id, params.flags, |
| 1244 | feedback)); |
Peng Huang | 6bf9277 | 2017-11-30 18:57:08 | [diff] [blame] | 1245 | } |
| 1246 | |
stanisc | eed2187b | 2017-02-15 19:56:05 | [diff] [blame] | 1247 | void InProcessCommandBuffer::AddFilter(IPC::MessageFilter* message_filter) { |
| 1248 | NOTREACHED(); |
| 1249 | } |
| 1250 | |
| 1251 | int32_t InProcessCommandBuffer::GetRouteID() const { |
| 1252 | NOTREACHED(); |
| 1253 | return 0; |
| 1254 | } |
| 1255 | |
fsamuel | 58b5a22 | 2016-11-23 23:50:24 | [diff] [blame] | 1256 | void InProcessCommandBuffer::DidSwapBuffersCompleteOnOriginThread( |
| 1257 | SwapBuffersCompleteParams params) { |
Eric Karl | b6b2c63 | 2018-05-07 22:45:04 | [diff] [blame] | 1258 | if (gpu_control_client_) |
| 1259 | gpu_control_client_->OnGpuControlSwapBuffersCompleted(params); |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 1260 | } |
| 1261 | |
Peng Huang | 6bf9277 | 2017-11-30 18:57:08 | [diff] [blame] | 1262 | void InProcessCommandBuffer::BufferPresentedOnOriginThread( |
| 1263 | uint64_t swap_id, |
Eric Karl | b6b2c63 | 2018-05-07 22:45:04 | [diff] [blame] | 1264 | uint32_t flags, |
Peng Huang | 6bf9277 | 2017-11-30 18:57:08 | [diff] [blame] | 1265 | const gfx::PresentationFeedback& feedback) { |
Sadrul Habib Chowdhury | f74aa5cb | 2018-05-19 01:08:03 | [diff] [blame] | 1266 | if (gpu_control_client_) |
| 1267 | gpu_control_client_->OnSwapBufferPresented(swap_id, feedback); |
Eric Karl | b6b2c63 | 2018-05-07 22:45:04 | [diff] [blame] | 1268 | if (flags & gpu::SwapBuffersFlags::kPresentationFeedback || |
| 1269 | (flags & gpu::SwapBuffersFlags::kVSyncParams && |
| 1270 | feedback.flags & gfx::PresentationFeedback::kVSync)) { |
Eric Karl | b6b2c63 | 2018-05-07 22:45:04 | [diff] [blame] | 1271 | if (update_vsync_parameters_completion_callback_ && |
| 1272 | feedback.timestamp != base::TimeTicks()) |
| 1273 | update_vsync_parameters_completion_callback_.Run(feedback.timestamp, |
| 1274 | feedback.interval); |
| 1275 | } |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 1276 | } |
| 1277 | |
| 1278 | void InProcessCommandBuffer::SetUpdateVSyncParametersCallback( |
| 1279 | const UpdateVSyncParametersCallback& callback) { |
| 1280 | update_vsync_parameters_completion_callback_ = callback; |
| 1281 | } |
| 1282 | |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 1283 | namespace { |
| 1284 | |
skyostil | 0ad2c54 | 2015-05-07 11:52:01 | [diff] [blame] | 1285 | void PostCallback( |
| 1286 | const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 1287 | base::OnceClosure callback) { |
skyostil | 0ad2c54 | 2015-05-07 11:52:01 | [diff] [blame] | 1288 | // 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 Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 1291 | task_runner->PostTask(FROM_HERE, std::move(callback)); |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 1292 | } else { |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 1293 | std::move(callback).Run(); |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 1294 | } |
| 1295 | } |
| 1296 | |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 1297 | void RunOnTargetThread(base::OnceClosure callback) { |
| 1298 | DCHECK(!callback.is_null()); |
| 1299 | std::move(callback).Run(); |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 1300 | } |
| 1301 | |
| 1302 | } // anonymous namespace |
| 1303 | |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 1304 | base::OnceClosure InProcessCommandBuffer::WrapCallback( |
| 1305 | base::OnceClosure callback) { |
[email protected] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 1306 | // Make sure the callback gets deleted on the target thread by passing |
| 1307 | // ownership. |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 1308 | 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] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 1316 | return wrapped_callback; |
| 1317 | } |
| 1318 | |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 1319 | InProcessCommandBuffer::GpuTask::GpuTask(base::OnceClosure callback, |
fsamuel | edc0c2c | 2016-11-18 22:28:04 | [diff] [blame] | 1320 | uint32_t order_number) |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 1321 | : once_closure_(std::move(callback)), order_number_(order_number) {} |
| 1322 | |
| 1323 | InProcessCommandBuffer::GpuTask::GpuTask(base::RepeatingClosure callback, |
| 1324 | uint32_t order_number) |
| 1325 | : repeating_closure_(std::move(callback)), order_number_(order_number) {} |
boliu | c5befe7 | 2015-07-21 19:08:56 | [diff] [blame] | 1326 | |
Chris Watkins | 8103077 | 2017-12-07 01:20:56 | [diff] [blame] | 1327 | InProcessCommandBuffer::GpuTask::~GpuTask() = default; |
boliu | c5befe7 | 2015-07-21 19:08:56 | [diff] [blame] | 1328 | |
Jonathan Backer | bd345c1f | 2018-02-14 21:44:23 | [diff] [blame] | 1329 | void 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] | 92dd7777 | 2013-08-01 23:57:56 | [diff] [blame] | 1338 | } // namespace gpu |