OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/mus/common/gpu_service.h" | 5 #include "components/mus/common/gpu_service.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/memory/singleton.h" | 8 #include "base/memory/singleton.h" |
9 #include "base/run_loop.h" | |
9 #include "components/mus/common/gpu_type_converters.h" | 10 #include "components/mus/common/gpu_type_converters.h" |
10 #include "components/mus/common/mojo_gpu_memory_buffer_manager.h" | |
11 #include "components/mus/common/switches.h" | 11 #include "components/mus/common/switches.h" |
12 #include "components/mus/public/interfaces/gpu_service.mojom.h" | 12 #include "components/mus/public/interfaces/gpu_service.mojom.h" |
13 #include "mojo/public/cpp/bindings/sync_call_restrictions.h" | 13 #include "mojo/public/cpp/bindings/sync_call_restrictions.h" |
14 #include "mojo/public/cpp/system/platform_handle.h" | 14 #include "mojo/public/cpp/system/platform_handle.h" |
15 #include "services/shell/public/cpp/connector.h" | 15 #include "services/shell/public/cpp/connector.h" |
16 | 16 |
17 namespace mus { | 17 namespace mus { |
18 | 18 |
19 namespace { | |
20 | |
21 void PostTask(scoped_refptr<base::SingleThreadTaskRunner> runner, | |
22 const base::Closure& callback) { | |
23 runner->PostTask(FROM_HERE, callback); | |
piman
2016/06/22 17:58:10
nit: can we move the FROM_HERE to the caller? I.e.
Peng
2016/06/22 19:28:30
Done.
| |
24 } | |
25 } | |
26 | |
19 GpuService::GpuService() | 27 GpuService::GpuService() |
20 : main_message_loop_(base::MessageLoop::current()), | 28 : main_message_loop_(nullptr), |
29 connector_(nullptr), | |
21 shutdown_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC, | 30 shutdown_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC, |
22 base::WaitableEvent::InitialState::NOT_SIGNALED), | 31 base::WaitableEvent::InitialState::NOT_SIGNALED), |
23 io_thread_("GPUIOThread"), | 32 io_thread_("GPUIOThread"), |
24 gpu_memory_buffer_manager_(new MojoGpuMemoryBufferManager) { | 33 gpu_memory_buffer_manager_(new MojoGpuMemoryBufferManager), |
34 is_establishing_(false), | |
35 establishing_condition_(&lock_) { | |
25 base::Thread::Options thread_options(base::MessageLoop::TYPE_IO, 0); | 36 base::Thread::Options thread_options(base::MessageLoop::TYPE_IO, 0); |
26 thread_options.priority = base::ThreadPriority::NORMAL; | 37 thread_options.priority = base::ThreadPriority::NORMAL; |
27 CHECK(io_thread_.StartWithOptions(thread_options)); | 38 CHECK(io_thread_.StartWithOptions(thread_options)); |
28 } | 39 } |
29 | 40 |
30 GpuService::~GpuService() {} | 41 GpuService::~GpuService() {} |
31 | 42 |
32 // static | 43 // static |
33 bool GpuService::UseChromeGpuCommandBuffer() { | 44 bool GpuService::UseChromeGpuCommandBuffer() { |
34 return base::CommandLine::ForCurrentProcess()->HasSwitch( | 45 return base::CommandLine::ForCurrentProcess()->HasSwitch( |
35 switches::kUseChromeGpuCommandBufferInMus); | 46 switches::kUseChromeGpuCommandBufferInMus); |
36 } | 47 } |
37 | 48 |
38 // static | 49 // static |
50 void GpuService::Initialize(shell::Connector* connector) { | |
51 GetInstance()->Init(connector); | |
52 } | |
53 | |
54 // static | |
39 GpuService* GpuService::GetInstance() { | 55 GpuService* GpuService::GetInstance() { |
40 return base::Singleton<GpuService, | 56 return base::Singleton<GpuService, |
piman
2016/06/22 17:58:10
Because initialization needs to be explicit, could
Peng
2016/06/22 19:28:30
Done.
| |
41 base::LeakySingletonTraits<GpuService>>::get(); | 57 base::LeakySingletonTraits<GpuService>>::get(); |
42 } | 58 } |
43 | 59 |
44 scoped_refptr<gpu::GpuChannelHost> GpuService::EstablishGpuChannel( | 60 void GpuService::EstablishGpuChannel(const base::Closure& callback) { |
45 shell::Connector* connector) { | 61 DCHECK(main_message_loop_); |
62 DCHECK(connector_); | |
63 | |
46 base::AutoLock auto_lock(lock_); | 64 base::AutoLock auto_lock(lock_); |
65 auto runner = base::ThreadTaskRunnerHandle::Get(); | |
66 if (GetGpuChannelLocked()) { | |
67 runner->PostTask(FROM_HERE, callback); | |
68 return; | |
69 } | |
70 base::Closure wrapper_callback = | |
71 IsMainThread() ? callback : base::Bind(PostTask, runner, callback); | |
72 establish_callbacks_.push_back(wrapper_callback); | |
73 | |
74 if (!is_establishing_) { | |
75 is_establishing_ = true; | |
76 main_message_loop_->task_runner()->PostTask( | |
77 FROM_HERE, base::Bind(&GpuService::EstablishGpuChannelOnMainThread, | |
78 base::Unretained(this))); | |
79 } | |
80 } | |
81 | |
82 scoped_refptr<gpu::GpuChannelHost> GpuService::EstablishGpuChannelSync() { | |
83 DCHECK(main_message_loop_); | |
84 DCHECK(connector_); | |
85 | |
86 base::AutoLock auto_lock(lock_); | |
87 if (GetGpuChannelLocked()) | |
88 return gpu_channel_; | |
89 | |
90 if (!IsMainThread()) { | |
91 if (!is_establishing_) { | |
92 // Create an establishing gpu channel task, if there isn't one. | |
93 is_establishing_ = true; | |
94 main_message_loop_->task_runner()->PostTask( | |
95 FROM_HERE, base::Bind(&GpuService::EstablishGpuChannelOnMainThread, | |
96 base::Unretained(this))); | |
97 } | |
98 // Wait until the pending establishing task is finished. | |
99 do { | |
100 establishing_condition_.Wait(); | |
101 } while (is_establishing_); | |
102 } else { | |
103 if (is_establishing_) { | |
104 // A establishing task has been posted and we are on the main thread, | |
105 // so we have to run a nest run loop. | |
piman
2016/06/22 17:58:10
This seems bad.
Could we instead run the code belo
Peng
2016/06/22 19:28:30
Done.
| |
106 base::RunLoop run_loop; | |
107 DCHECK(quite_run_loop_closure_.is_null()); | |
108 quite_run_loop_closure_ = run_loop.QuitClosure(); | |
109 { | |
110 base::AutoUnlock auto_unlock(lock_); | |
111 run_loop.Run(); | |
112 } | |
113 DCHECK(quite_run_loop_closure_.is_null()); | |
114 DCHECK(!is_establishing_); | |
115 } else { | |
116 is_establishing_ = true; | |
117 int client_id = 0; | |
118 mojom::ChannelHandlePtr channel_handle; | |
119 mojom::GpuInfoPtr gpu_info; | |
120 mus::mojom::GpuServicePtr gpu_service; | |
121 connector_->ConnectToInterface("mojo:mus", &gpu_service); | |
122 { | |
123 // Unlock the |lock_| during the sync mojo method call. | |
124 base::AutoUnlock auto_unlock(lock_); | |
125 // TODO(penghuang): Remove the ScopedAllowSyncCall when HW rendering is | |
126 // enabled in mus chrome. | |
127 mojo::SyncCallRestrictions::ScopedAllowSyncCall allow_sync_call; | |
128 if (!gpu_service->EstablishGpuChannel(&client_id, &channel_handle, | |
129 &gpu_info)) { | |
130 DLOG(WARNING) | |
131 << "Channel encountered error while establishing gpu channel."; | |
piman
2016/06/22 17:58:10
should you return nullptr here?
Peng
2016/06/22 19:28:30
Done.
| |
132 } | |
133 } | |
134 const bool locked = true; | |
135 EstablishGpuChannelOnMainThreadDone( | |
136 locked, client_id, std::move(channel_handle), std::move(gpu_info)); | |
137 } | |
138 } | |
139 return gpu_channel_; | |
140 } | |
141 | |
142 scoped_refptr<gpu::GpuChannelHost> GpuService::GetGpuChannel() { | |
143 base::AutoLock auto_lock(lock_); | |
144 return GetGpuChannelLocked(); | |
145 } | |
146 | |
147 void GpuService::Init(shell::Connector* connector) { | |
148 DCHECK(!main_message_loop_); | |
149 DCHECK(!connector_); | |
150 main_message_loop_ = base::MessageLoop::current(); | |
151 connector_ = connector; | |
152 DCHECK(main_message_loop_); | |
153 DCHECK(connector_); | |
154 } | |
155 | |
156 scoped_refptr<gpu::GpuChannelHost> GpuService::GetGpuChannelLocked() { | |
47 if (gpu_channel_ && gpu_channel_->IsLost()) { | 157 if (gpu_channel_ && gpu_channel_->IsLost()) { |
48 gpu_channel_->DestroyChannel(); | 158 main_message_loop_->task_runner()->PostTask( |
159 FROM_HERE, | |
160 base::Bind(&gpu::GpuChannelHost::DestroyChannel, gpu_channel_)); | |
49 gpu_channel_ = nullptr; | 161 gpu_channel_ = nullptr; |
50 } | 162 } |
163 return gpu_channel_; | |
164 } | |
51 | 165 |
52 if (gpu_channel_) | 166 void GpuService::EstablishGpuChannelOnMainThread() { |
53 return gpu_channel_; | 167 base::AutoLock auto_lock(lock_); |
168 DCHECK(IsMainThread()); | |
169 DCHECK(!gpu_channel_); | |
170 DCHECK(connector_); | |
54 | 171 |
55 mus::mojom::GpuServicePtr gpu_service; | 172 mus::mojom::GpuServicePtr gpu_service; |
56 connector->ConnectToInterface("mojo:mus", &gpu_service); | 173 connector_->ConnectToInterface("mojo:mus", &gpu_service); |
174 const bool locked = false; | |
175 gpu_service->EstablishGpuChannel( | |
176 base::Bind(&GpuService::EstablishGpuChannelOnMainThreadDone, | |
177 base::Unretained(this), locked)); | |
178 } | |
57 | 179 |
58 int client_id = 0; | 180 void GpuService::EstablishGpuChannelOnMainThreadDone( |
59 mojom::ChannelHandlePtr channel_handle; | 181 bool locked, |
60 mojom::GpuInfoPtr gpu_info; | 182 int client_id, |
61 { | 183 mojom::ChannelHandlePtr channel_handle, |
62 // TODO(penghuang): Remove the ScopedAllowSyncCall when HW rendering is | 184 mojom::GpuInfoPtr gpu_info) { |
63 // enabled in mus chrome. | 185 DCHECK(IsMainThread()); |
64 mojo::SyncCallRestrictions::ScopedAllowSyncCall allow_sync_call; | 186 scoped_refptr<gpu::GpuChannelHost> gpu_channel; |
65 if (!gpu_service->EstablishGpuChannel(&client_id, &channel_handle, | 187 if (client_id) { |
66 &gpu_info)) { | 188 // TODO(penghuang): Get the real gpu info from mus. |
67 DLOG(WARNING) | 189 gpu_channel = gpu::GpuChannelHost::Create( |
68 << "Channel encountered error while establishing gpu channel."; | 190 this, client_id, gpu::GPUInfo(), |
69 return nullptr; | 191 channel_handle.To<IPC::ChannelHandle>(), &shutdown_event_, |
70 } | 192 gpu_memory_buffer_manager_.get()); |
71 } | 193 } |
72 | 194 |
73 // TODO(penghuang): Get the real gpu info from mus. | 195 std::unique_ptr<base::AutoLock> auto_lock; |
74 gpu_channel_ = gpu::GpuChannelHost::Create( | 196 if (!locked) |
75 this, client_id, gpu::GPUInfo(), channel_handle.To<IPC::ChannelHandle>(), | 197 auto_lock = base::MakeUnique<base::AutoLock>(lock_); |
76 &shutdown_event_, gpu_memory_buffer_manager_.get()); | 198 DCHECK(is_establishing_); |
77 return gpu_channel_; | 199 DCHECK(!gpu_channel_); |
200 | |
201 is_establishing_ = false; | |
202 gpu_channel_ = gpu_channel; | |
203 establishing_condition_.Broadcast(); | |
204 | |
205 for (const auto& i : establish_callbacks_) | |
206 i.Run(); | |
207 establish_callbacks_.clear(); | |
208 if (quite_run_loop_closure_) { | |
209 quite_run_loop_closure_.Run(); | |
210 quite_run_loop_closure_.Reset; | |
211 } | |
78 } | 212 } |
79 | 213 |
80 bool GpuService::IsMainThread() { | 214 bool GpuService::IsMainThread() { |
81 return base::MessageLoop::current() == main_message_loop_; | 215 return base::MessageLoop::current() == main_message_loop_; |
82 } | 216 } |
83 | 217 |
84 scoped_refptr<base::SingleThreadTaskRunner> | 218 scoped_refptr<base::SingleThreadTaskRunner> |
85 GpuService::GetIOThreadTaskRunner() { | 219 GpuService::GetIOThreadTaskRunner() { |
86 return io_thread_.task_runner(); | 220 return io_thread_.task_runner(); |
87 } | 221 } |
(...skipping 11 matching lines...) Expand all Loading... | |
99 MojoResult result = mojo::UnwrapSharedMemoryHandle( | 233 MojoResult result = mojo::UnwrapSharedMemoryHandle( |
100 std::move(handle), &platform_handle, &shared_memory_size, &readonly); | 234 std::move(handle), &platform_handle, &shared_memory_size, &readonly); |
101 if (result != MOJO_RESULT_OK) | 235 if (result != MOJO_RESULT_OK) |
102 return nullptr; | 236 return nullptr; |
103 DCHECK_EQ(shared_memory_size, size); | 237 DCHECK_EQ(shared_memory_size, size); |
104 | 238 |
105 return base::MakeUnique<base::SharedMemory>(platform_handle, readonly); | 239 return base::MakeUnique<base::SharedMemory>(platform_handle, readonly); |
106 } | 240 } |
107 | 241 |
108 } // namespace mus | 242 } // namespace mus |
OLD | NEW |