OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "content/browser/gpu/browser_gpu_channel_host_factory.h" | 5 #include "content/browser/gpu/browser_gpu_channel_host_factory.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/threading/thread_restrictions.h" | 8 #include "base/threading/thread_restrictions.h" |
9 #include "content/browser/gpu/gpu_data_manager_impl.h" | 9 #include "content/browser/gpu/gpu_data_manager_impl.h" |
10 #include "content/browser/gpu/gpu_process_host.h" | 10 #include "content/browser/gpu/gpu_process_host.h" |
11 #include "content/browser/gpu/gpu_surface_tracker.h" | 11 #include "content/browser/gpu/gpu_surface_tracker.h" |
12 #include "content/common/gpu/gpu_messages.h" | 12 #include "content/common/gpu/gpu_messages.h" |
13 #include "content/common/child_process_host_impl.h" | 13 #include "content/common/child_process_host_impl.h" |
14 #include "content/public/browser/browser_thread.h" | 14 #include "content/public/browser/browser_thread.h" |
15 #include "content/public/common/content_client.h" | 15 #include "content/public/common/content_client.h" |
16 | 16 |
17 namespace content { | 17 namespace content { |
18 | 18 |
19 BrowserGpuChannelHostFactory* BrowserGpuChannelHostFactory::instance_ = NULL; | 19 BrowserGpuChannelHostFactory* BrowserGpuChannelHostFactory::instance_ = NULL; |
20 | 20 |
21 BrowserGpuChannelHostFactory::CreateRequest::CreateRequest() | 21 BrowserGpuChannelHostFactory::CreateRequest::CreateRequest() |
22 : event(false, false), | 22 : event(false, false), |
| 23 gpu_host_id(0), |
23 route_id(MSG_ROUTING_NONE) { | 24 route_id(MSG_ROUTING_NONE) { |
24 } | 25 } |
25 | 26 |
26 BrowserGpuChannelHostFactory::CreateRequest::~CreateRequest() { | 27 BrowserGpuChannelHostFactory::CreateRequest::~CreateRequest() { |
27 } | 28 } |
28 | 29 |
29 BrowserGpuChannelHostFactory::EstablishRequest::EstablishRequest() | 30 BrowserGpuChannelHostFactory::EstablishRequest::EstablishRequest( |
30 : event(false, false) { | 31 CauseForGpuLaunch cause) |
| 32 : event(false, false), |
| 33 cause_for_gpu_launch(cause), |
| 34 gpu_host_id(0), |
| 35 reused_gpu_process(true) { |
31 } | 36 } |
32 | 37 |
33 BrowserGpuChannelHostFactory::EstablishRequest::~EstablishRequest() { | 38 BrowserGpuChannelHostFactory::EstablishRequest::~EstablishRequest() { |
34 } | 39 } |
35 | 40 |
36 void BrowserGpuChannelHostFactory::Initialize() { | 41 void BrowserGpuChannelHostFactory::Initialize() { |
37 instance_ = new BrowserGpuChannelHostFactory(); | 42 instance_ = new BrowserGpuChannelHostFactory(); |
38 } | 43 } |
39 | 44 |
40 void BrowserGpuChannelHostFactory::Terminate() { | 45 void BrowserGpuChannelHostFactory::Terminate() { |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 // We're blocking the UI thread, which is generally undesirable. | 128 // We're blocking the UI thread, which is generally undesirable. |
124 // In this case we need to wait for this before we can show any UI /anyway/, | 129 // In this case we need to wait for this before we can show any UI /anyway/, |
125 // so it won't cause additional jank. | 130 // so it won't cause additional jank. |
126 // TODO(piman): Make this asynchronous (http://crbug.com/125248). | 131 // TODO(piman): Make this asynchronous (http://crbug.com/125248). |
127 base::ThreadRestrictions::ScopedAllowWait allow_wait; | 132 base::ThreadRestrictions::ScopedAllowWait allow_wait; |
128 request.event.Wait(); | 133 request.event.Wait(); |
129 return request.route_id; | 134 return request.route_id; |
130 } | 135 } |
131 | 136 |
132 void BrowserGpuChannelHostFactory::EstablishGpuChannelOnIO( | 137 void BrowserGpuChannelHostFactory::EstablishGpuChannelOnIO( |
133 EstablishRequest* request, | 138 EstablishRequest* request) { |
134 CauseForGpuLaunch cause_for_gpu_launch) { | |
135 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_); | 139 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_); |
136 if (!host) { | 140 if (!host) { |
137 host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, | 141 host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, |
138 cause_for_gpu_launch); | 142 request->cause_for_gpu_launch); |
139 if (!host) { | 143 if (!host) { |
140 request->event.Signal(); | 144 request->event.Signal(); |
141 return; | 145 return; |
142 } | 146 } |
143 gpu_host_id_ = host->host_id(); | 147 gpu_host_id_ = host->host_id(); |
| 148 request->reused_gpu_process = false; |
| 149 } else { |
| 150 if (host->host_id() == request->gpu_host_id) { |
| 151 // We come here if we retried to establish the channel because of a |
| 152 // failure in GpuChannelEstablishedOnIO, but we ended up with the same |
| 153 // process ID, meaning the failure was not because of a channel error, but |
| 154 // another reason. So fail now. |
| 155 request->event.Signal(); |
| 156 return; |
| 157 } |
| 158 request->reused_gpu_process = true; |
144 } | 159 } |
| 160 request->gpu_host_id = gpu_host_id_; |
145 | 161 |
146 host->EstablishGpuChannel( | 162 host->EstablishGpuChannel( |
147 gpu_client_id_, | 163 gpu_client_id_, |
148 true, | 164 true, |
149 base::Bind(&BrowserGpuChannelHostFactory::GpuChannelEstablishedOnIO, | 165 base::Bind(&BrowserGpuChannelHostFactory::GpuChannelEstablishedOnIO, |
| 166 base::Unretained(this), |
150 request)); | 167 request)); |
151 } | 168 } |
152 | 169 |
153 // static | |
154 void BrowserGpuChannelHostFactory::GpuChannelEstablishedOnIO( | 170 void BrowserGpuChannelHostFactory::GpuChannelEstablishedOnIO( |
155 EstablishRequest* request, | 171 EstablishRequest* request, |
156 const IPC::ChannelHandle& channel_handle, | 172 const IPC::ChannelHandle& channel_handle, |
157 const GPUInfo& gpu_info) { | 173 const GPUInfo& gpu_info) { |
158 request->channel_handle = channel_handle; | 174 if (channel_handle.name.empty() && request->reused_gpu_process) { |
159 request->gpu_info = gpu_info; | 175 // We failed after re-using the GPU process, but it may have died in the |
160 request->event.Signal(); | 176 // mean time. Retry to have a chance to create a fresh GPU process. |
| 177 EstablishGpuChannelOnIO(request); |
| 178 } else { |
| 179 request->channel_handle = channel_handle; |
| 180 request->gpu_info = gpu_info; |
| 181 request->event.Signal(); |
| 182 } |
161 } | 183 } |
162 | 184 |
163 GpuChannelHost* BrowserGpuChannelHostFactory::EstablishGpuChannelSync( | 185 GpuChannelHost* BrowserGpuChannelHostFactory::EstablishGpuChannelSync( |
164 CauseForGpuLaunch cause_for_gpu_launch) { | 186 CauseForGpuLaunch cause_for_gpu_launch) { |
165 if (gpu_channel_.get()) { | 187 if (gpu_channel_.get()) { |
166 // Recreate the channel if it has been lost. | 188 // Recreate the channel if it has been lost. |
167 if (gpu_channel_->state() == GpuChannelHost::kLost) | 189 if (gpu_channel_->state() == GpuChannelHost::kLost) |
168 gpu_channel_ = NULL; | 190 gpu_channel_ = NULL; |
169 else | 191 else |
170 return gpu_channel_.get(); | 192 return gpu_channel_.get(); |
171 } | 193 } |
172 // Ensure initialization on the main thread. | 194 // Ensure initialization on the main thread. |
173 GpuDataManagerImpl::GetInstance(); | 195 GpuDataManagerImpl::GetInstance(); |
174 | 196 |
175 EstablishRequest request; | 197 EstablishRequest request(cause_for_gpu_launch); |
176 GetIOLoopProxy()->PostTask( | 198 GetIOLoopProxy()->PostTask( |
177 FROM_HERE, | 199 FROM_HERE, |
178 base::Bind( | 200 base::Bind( |
179 &BrowserGpuChannelHostFactory::EstablishGpuChannelOnIO, | 201 &BrowserGpuChannelHostFactory::EstablishGpuChannelOnIO, |
180 base::Unretained(this), | 202 base::Unretained(this), |
181 &request, | 203 &request)); |
182 cause_for_gpu_launch)); | |
183 | 204 |
184 { | 205 { |
185 // We're blocking the UI thread, which is generally undesirable. | 206 // We're blocking the UI thread, which is generally undesirable. |
186 // In this case we need to wait for this before we can show any UI /anyway/, | 207 // In this case we need to wait for this before we can show any UI /anyway/, |
187 // so it won't cause additional jank. | 208 // so it won't cause additional jank. |
188 // TODO(piman): Make this asynchronous (http://crbug.com/125248). | 209 // TODO(piman): Make this asynchronous (http://crbug.com/125248). |
189 base::ThreadRestrictions::ScopedAllowWait allow_wait; | 210 base::ThreadRestrictions::ScopedAllowWait allow_wait; |
190 request.event.Wait(); | 211 request.event.Wait(); |
191 } | 212 } |
192 | 213 |
193 if (request.channel_handle.name.empty()) | 214 if (request.channel_handle.name.empty()) |
194 return NULL; | 215 return NULL; |
195 | 216 |
196 gpu_channel_ = new GpuChannelHost(this, gpu_host_id_, gpu_client_id_); | 217 gpu_channel_ = new GpuChannelHost(this, request.gpu_host_id, gpu_client_id_); |
197 gpu_channel_->set_gpu_info(request.gpu_info); | 218 gpu_channel_->set_gpu_info(request.gpu_info); |
198 content::GetContentClient()->SetGpuInfo(request.gpu_info); | 219 content::GetContentClient()->SetGpuInfo(request.gpu_info); |
199 | 220 |
200 // Connect to the GPU process if a channel name was received. | 221 // Connect to the GPU process if a channel name was received. |
201 gpu_channel_->Connect(request.channel_handle); | 222 gpu_channel_->Connect(request.channel_handle); |
202 | 223 |
203 return gpu_channel_.get(); | 224 return gpu_channel_.get(); |
204 } | 225 } |
205 | 226 |
206 } // namespace content | 227 } // namespace content |
OLD | NEW |