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

Side by Side Diff: services/ui/public/cpp/gpu_service.cc

Issue 2257713002: services/ui: GpuService should only be used from a single thread. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@gpu-service-cleanup
Patch Set: tot merge Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « services/ui/public/cpp/gpu_service.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "services/ui/public/cpp/gpu_service.h" 5 #include "services/ui/public/cpp/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/threading/thread_task_runner_handle.h" 9 #include "base/threading/thread_task_runner_handle.h"
10 #include "build/build_config.h" 10 #include "build/build_config.h"
11 #include "mojo/public/cpp/bindings/sync_call_restrictions.h" 11 #include "mojo/public/cpp/bindings/sync_call_restrictions.h"
12 #include "mojo/public/cpp/system/platform_handle.h" 12 #include "mojo/public/cpp/system/platform_handle.h"
13 #include "services/shell/public/cpp/connector.h" 13 #include "services/shell/public/cpp/connector.h"
14 #include "services/ui/common/gpu_type_converters.h" 14 #include "services/ui/common/gpu_type_converters.h"
15 #include "services/ui/common/switches.h" 15 #include "services/ui/common/switches.h"
16 #include "services/ui/public/cpp/mojo_gpu_memory_buffer_manager.h" 16 #include "services/ui/public/cpp/mojo_gpu_memory_buffer_manager.h"
17 #include "services/ui/public/interfaces/gpu_service.mojom.h" 17 #include "services/ui/public/interfaces/gpu_service.mojom.h"
18 18
19 namespace ui { 19 namespace ui {
20 20
21 namespace {
22
23 void PostTask(scoped_refptr<base::SingleThreadTaskRunner> runner,
24 const tracked_objects::Location& from_here,
25 const gpu::GpuChannelEstablishedCallback& callback,
26 scoped_refptr<gpu::GpuChannelHost> established_channel_host) {
27 runner->PostTask(from_here,
28 base::Bind(callback, std::move(established_channel_host)));
29 }
30
31 } // namespace
32
33 GpuService::GpuService(shell::Connector* connector, 21 GpuService::GpuService(shell::Connector* connector,
34 scoped_refptr<base::SingleThreadTaskRunner> task_runner) 22 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
35 : main_task_runner_(base::ThreadTaskRunnerHandle::Get()), 23 : main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
36 io_task_runner_(std::move(task_runner)), 24 io_task_runner_(std::move(task_runner)),
37 connector_(connector), 25 connector_(connector),
38 shutdown_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC, 26 shutdown_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
39 base::WaitableEvent::InitialState::NOT_SIGNALED), 27 base::WaitableEvent::InitialState::NOT_SIGNALED),
40 gpu_memory_buffer_manager_(new MojoGpuMemoryBufferManager), 28 gpu_memory_buffer_manager_(new MojoGpuMemoryBufferManager) {
41 is_establishing_(false),
42 establishing_condition_(&lock_) {
43 DCHECK(main_task_runner_); 29 DCHECK(main_task_runner_);
44 DCHECK(connector_); 30 DCHECK(connector_);
45 if (!io_task_runner_) { 31 if (!io_task_runner_) {
46 io_thread_.reset(new base::Thread("GPUIOThread")); 32 io_thread_.reset(new base::Thread("GPUIOThread"));
47 base::Thread::Options thread_options(base::MessageLoop::TYPE_IO, 0); 33 base::Thread::Options thread_options(base::MessageLoop::TYPE_IO, 0);
48 thread_options.priority = base::ThreadPriority::NORMAL; 34 thread_options.priority = base::ThreadPriority::NORMAL;
49 CHECK(io_thread_->StartWithOptions(thread_options)); 35 CHECK(io_thread_->StartWithOptions(thread_options));
50 io_task_runner_ = io_thread_->task_runner(); 36 io_task_runner_ = io_thread_->task_runner();
51 } 37 }
52 } 38 }
53 39
54 GpuService::~GpuService() { 40 GpuService::~GpuService() {
55 DCHECK(IsMainThread()); 41 DCHECK(IsMainThread());
42 for (const auto& callback : establish_callbacks_)
43 callback.Run(nullptr);
44 shutdown_event_.Signal();
56 if (gpu_channel_) 45 if (gpu_channel_)
57 gpu_channel_->DestroyChannel(); 46 gpu_channel_->DestroyChannel();
58 } 47 }
59 48
60 // static 49 // static
61 std::unique_ptr<GpuService> GpuService::Create( 50 std::unique_ptr<GpuService> GpuService::Create(
62 shell::Connector* connector, 51 shell::Connector* connector,
63 scoped_refptr<base::SingleThreadTaskRunner> task_runner) { 52 scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
64 return base::WrapUnique(new GpuService(connector, std::move(task_runner))); 53 return base::WrapUnique(new GpuService(connector, std::move(task_runner)));
65 } 54 }
66 55
67 void GpuService::EstablishGpuChannel( 56 void GpuService::EstablishGpuChannel(
68 const gpu::GpuChannelEstablishedCallback& callback) { 57 const gpu::GpuChannelEstablishedCallback& callback) {
69 base::AutoLock auto_lock(lock_); 58 DCHECK(IsMainThread());
70 auto runner = base::ThreadTaskRunnerHandle::Get(); 59 scoped_refptr<gpu::GpuChannelHost> channel = GetGpuChannel();
71 scoped_refptr<gpu::GpuChannelHost> channel = GetGpuChannelLocked();
72 if (channel) { 60 if (channel) {
73 PostTask(runner, FROM_HERE, callback, std::move(channel)); 61 main_task_runner_->PostTask(FROM_HERE,
62 base::Bind(callback, std::move(channel)));
74 return; 63 return;
75 } 64 }
76 establish_callbacks_.push_back( 65 establish_callbacks_.push_back(callback);
77 base::Bind(PostTask, runner, FROM_HERE, callback)); 66 if (gpu_service_)
78 if (!is_establishing_) { 67 return;
79 is_establishing_ = true; 68
80 main_task_runner_->PostTask( 69 connector_->ConnectToInterface("mojo:ui", &gpu_service_);
81 FROM_HERE, base::Bind(&GpuService::EstablishGpuChannelOnMainThread, 70 gpu_service_->EstablishGpuChannel(
82 base::Unretained(this))); 71 base::Bind(&GpuService::OnEstablishedGpuChannel, base::Unretained(this)));
83 }
84 } 72 }
85 73
86 scoped_refptr<gpu::GpuChannelHost> GpuService::EstablishGpuChannelSync() { 74 scoped_refptr<gpu::GpuChannelHost> GpuService::EstablishGpuChannelSync() {
87 base::AutoLock auto_lock(lock_); 75 DCHECK(IsMainThread());
88 if (GetGpuChannelLocked()) 76 if (GetGpuChannel())
89 return gpu_channel_; 77 return gpu_channel_;
90 78
91 if (IsMainThread()) { 79 int client_id = 0;
92 is_establishing_ = true; 80 mojo::ScopedMessagePipeHandle channel_handle;
93 EstablishGpuChannelOnMainThreadSyncLocked(); 81 gpu::GPUInfo gpu_info;
94 } else { 82 connector_->ConnectToInterface("mojo:ui", &gpu_service_);
95 if (!is_establishing_) {
96 // Create an establishing gpu channel task, if there isn't one.
97 is_establishing_ = true;
98 main_task_runner_->PostTask(
99 FROM_HERE, base::Bind(&GpuService::EstablishGpuChannelOnMainThread,
100 base::Unretained(this)));
101 }
102 83
103 // Wait until the pending establishing task is finished. 84 mojo::SyncCallRestrictions::ScopedAllowSyncCall allow_sync_call;
104 do { 85 if (!gpu_service_->EstablishGpuChannel(&client_id, &channel_handle,
105 establishing_condition_.Wait(); 86 &gpu_info)) {
106 } while (is_establishing_); 87 DLOG(WARNING)
88 << "Channel encountered error while establishing gpu channel.";
89 return nullptr;
107 } 90 }
91 OnEstablishedGpuChannel(client_id, std::move(channel_handle), gpu_info);
108 return gpu_channel_; 92 return gpu_channel_;
109 } 93 }
110 94
111 gpu::GpuMemoryBufferManager* GpuService::GetGpuMemoryBufferManager() { 95 gpu::GpuMemoryBufferManager* GpuService::GetGpuMemoryBufferManager() {
112 return gpu_memory_buffer_manager_.get(); 96 return gpu_memory_buffer_manager_.get();
113 } 97 }
114 98
115 scoped_refptr<gpu::GpuChannelHost> GpuService::GetGpuChannelLocked() { 99 scoped_refptr<gpu::GpuChannelHost> GpuService::GetGpuChannel() {
100 DCHECK(IsMainThread());
116 if (gpu_channel_ && gpu_channel_->IsLost()) { 101 if (gpu_channel_ && gpu_channel_->IsLost()) {
117 main_task_runner_->PostTask( 102 gpu_channel_->DestroyChannel();
118 FROM_HERE,
119 base::Bind(&gpu::GpuChannelHost::DestroyChannel, gpu_channel_));
120 gpu_channel_ = nullptr; 103 gpu_channel_ = nullptr;
121 } 104 }
122 return gpu_channel_; 105 return gpu_channel_;
123 } 106 }
124 107
125 void GpuService::EstablishGpuChannelOnMainThread() { 108 void GpuService::OnEstablishedGpuChannel(
126 base::AutoLock auto_lock(lock_);
127 DCHECK(IsMainThread());
128
129 // In GpuService::EstablishGpuChannelOnMainThreadSyncLocked(), we use the sync
130 // mojo EstablishGpuChannel call, after that call the gpu_service_ will be
131 // reset immediatelly. So gpu_service_ should be always null here.
132 DCHECK(!gpu_service_);
133
134 // is_establishing_ is false, it means GpuService::EstablishGpuChannelSync()
135 // has been used, and we don't need try to establish a new GPU channel
136 // anymore.
137 if (!is_establishing_)
138 return;
139
140 connector_->ConnectToInterface("mojo:ui", &gpu_service_);
141 const bool locked = false;
142 gpu_service_->EstablishGpuChannel(
143 base::Bind(&GpuService::EstablishGpuChannelOnMainThreadDone,
144 base::Unretained(this), locked));
145 }
146
147 void GpuService::EstablishGpuChannelOnMainThreadSyncLocked() {
148 DCHECK(IsMainThread());
149 DCHECK(is_establishing_);
150
151 // In browser process, EstablishGpuChannelSync() is only used by testing &
152 // GpuProcessTransportFactory::GetGLHelper(). For GetGLHelper(), it expects
153 // the gpu channel has been established, so it should not reach here.
154 // For testing, the asyc method should not be used.
155 // In renderer process, we only use EstablishGpuChannelSync().
156 // So the gpu_service_ should be null here.
157 DCHECK(!gpu_service_);
158
159 int client_id = 0;
160 mojo::ScopedMessagePipeHandle channel_handle;
161 gpu::GPUInfo gpu_info;
162 connector_->ConnectToInterface("mojo:ui", &gpu_service_);
163 {
164 base::AutoUnlock auto_unlock(lock_);
165 mojo::SyncCallRestrictions::ScopedAllowSyncCall allow_sync_call;
166 if (!gpu_service_->EstablishGpuChannel(&client_id, &channel_handle,
167 &gpu_info)) {
168 DLOG(WARNING)
169 << "Channel encountered error while establishing gpu channel.";
170 return;
171 }
172 }
173 const bool locked = true;
174 EstablishGpuChannelOnMainThreadDone(locked, client_id,
175 std::move(channel_handle), gpu_info);
176 }
177
178 void GpuService::EstablishGpuChannelOnMainThreadDone(
179 bool locked,
180 int client_id, 109 int client_id,
181 mojo::ScopedMessagePipeHandle channel_handle, 110 mojo::ScopedMessagePipeHandle channel_handle,
182 const gpu::GPUInfo& gpu_info) { 111 const gpu::GPUInfo& gpu_info) {
183 DCHECK(IsMainThread()); 112 DCHECK(IsMainThread());
184 scoped_refptr<gpu::GpuChannelHost> gpu_channel; 113 DCHECK(gpu_service_.get());
114 DCHECK(!gpu_channel_);
115
185 if (client_id) { 116 if (client_id) {
186 // TODO(penghuang): Get the real gpu info from mus. 117 // TODO(penghuang): Get the real gpu info from mus.
187 gpu_channel = gpu::GpuChannelHost::Create( 118 gpu_channel_ = gpu::GpuChannelHost::Create(
188 this, client_id, gpu::GPUInfo(), 119 this, client_id, gpu::GPUInfo(),
189 IPC::ChannelHandle(channel_handle.release()), &shutdown_event_, 120 IPC::ChannelHandle(channel_handle.release()), &shutdown_event_,
190 gpu_memory_buffer_manager_.get()); 121 gpu_memory_buffer_manager_.get());
191 } 122 }
192 123
193 auto auto_lock = base::WrapUnique<base::AutoLock>(
194 locked ? nullptr : new base::AutoLock(lock_));
195 DCHECK(is_establishing_);
196 DCHECK(!gpu_channel_);
197
198 is_establishing_ = false;
199 gpu_channel_ = gpu_channel;
200 establishing_condition_.Broadcast();
201 gpu_service_.reset(); 124 gpu_service_.reset();
202
203 for (const auto& i : establish_callbacks_) 125 for (const auto& i : establish_callbacks_)
204 i.Run(gpu_channel_); 126 i.Run(gpu_channel_);
205 establish_callbacks_.clear(); 127 establish_callbacks_.clear();
206 } 128 }
207 129
208 bool GpuService::IsMainThread() { 130 bool GpuService::IsMainThread() {
209 return main_task_runner_->BelongsToCurrentThread(); 131 return main_task_runner_->BelongsToCurrentThread();
210 } 132 }
211 133
212 scoped_refptr<base::SingleThreadTaskRunner> 134 scoped_refptr<base::SingleThreadTaskRunner>
(...skipping 14 matching lines...) Expand all
227 MojoResult result = mojo::UnwrapSharedMemoryHandle( 149 MojoResult result = mojo::UnwrapSharedMemoryHandle(
228 std::move(handle), &platform_handle, &shared_memory_size, &readonly); 150 std::move(handle), &platform_handle, &shared_memory_size, &readonly);
229 if (result != MOJO_RESULT_OK) 151 if (result != MOJO_RESULT_OK)
230 return nullptr; 152 return nullptr;
231 DCHECK_EQ(shared_memory_size, size); 153 DCHECK_EQ(shared_memory_size, size);
232 154
233 return base::MakeUnique<base::SharedMemory>(platform_handle, readonly); 155 return base::MakeUnique<base::SharedMemory>(platform_handle, readonly);
234 } 156 }
235 157
236 } // namespace ui 158 } // namespace ui
OLDNEW
« no previous file with comments | « services/ui/public/cpp/gpu_service.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698