| 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/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/location.h" | 9 #include "base/location.h" |
| 10 #include "base/profiler/scoped_tracker.h" | 10 #include "base/profiler/scoped_tracker.h" |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 #include "services/service_manager/runner/common/client_util.h" | 32 #include "services/service_manager/runner/common/client_util.h" |
| 33 | 33 |
| 34 namespace content { | 34 namespace content { |
| 35 | 35 |
| 36 BrowserGpuChannelHostFactory* BrowserGpuChannelHostFactory::instance_ = NULL; | 36 BrowserGpuChannelHostFactory* BrowserGpuChannelHostFactory::instance_ = NULL; |
| 37 | 37 |
| 38 class BrowserGpuChannelHostFactory::EstablishRequest | 38 class BrowserGpuChannelHostFactory::EstablishRequest |
| 39 : public base::RefCountedThreadSafe<EstablishRequest> { | 39 : public base::RefCountedThreadSafe<EstablishRequest> { |
| 40 public: | 40 public: |
| 41 static scoped_refptr<EstablishRequest> Create(int gpu_client_id, | 41 static scoped_refptr<EstablishRequest> Create(int gpu_client_id, |
| 42 uint64_t gpu_client_tracing_id, | 42 uint64_t gpu_client_tracing_id); |
| 43 int gpu_host_id); | |
| 44 void Wait(); | 43 void Wait(); |
| 45 void Cancel(); | 44 void Cancel(); |
| 46 | 45 |
| 47 int gpu_host_id() { return gpu_host_id_; } | |
| 48 IPC::ChannelHandle& channel_handle() { return channel_handle_; } | 46 IPC::ChannelHandle& channel_handle() { return channel_handle_; } |
| 49 gpu::GPUInfo gpu_info() { return gpu_info_; } | 47 gpu::GPUInfo gpu_info() { return gpu_info_; } |
| 50 | 48 |
| 51 private: | 49 private: |
| 52 friend class base::RefCountedThreadSafe<EstablishRequest>; | 50 friend class base::RefCountedThreadSafe<EstablishRequest>; |
| 53 explicit EstablishRequest(int gpu_client_id, | 51 explicit EstablishRequest(int gpu_client_id, uint64_t gpu_client_tracing_id); |
| 54 uint64_t gpu_client_tracing_id, | |
| 55 int gpu_host_id); | |
| 56 ~EstablishRequest() {} | 52 ~EstablishRequest() {} |
| 57 void EstablishOnIO(); | 53 void EstablishOnIO(); |
| 58 void OnEstablishedOnIO(const IPC::ChannelHandle& channel_handle, | 54 void OnEstablishedOnIO(const IPC::ChannelHandle& channel_handle, |
| 59 const gpu::GPUInfo& gpu_info); | 55 const gpu::GPUInfo& gpu_info, |
| 56 GpuProcessHost::EstablishChannelStatus status); |
| 60 void FinishOnIO(); | 57 void FinishOnIO(); |
| 61 void FinishOnMain(); | 58 void FinishOnMain(); |
| 62 | 59 |
| 63 base::WaitableEvent event_; | 60 base::WaitableEvent event_; |
| 64 const int gpu_client_id_; | 61 const int gpu_client_id_; |
| 65 const uint64_t gpu_client_tracing_id_; | 62 const uint64_t gpu_client_tracing_id_; |
| 66 int gpu_host_id_; | |
| 67 bool reused_gpu_process_; | |
| 68 IPC::ChannelHandle channel_handle_; | 63 IPC::ChannelHandle channel_handle_; |
| 69 gpu::GPUInfo gpu_info_; | 64 gpu::GPUInfo gpu_info_; |
| 70 bool finished_; | 65 bool finished_; |
| 71 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; | 66 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; |
| 72 }; | 67 }; |
| 73 | 68 |
| 74 scoped_refptr<BrowserGpuChannelHostFactory::EstablishRequest> | 69 scoped_refptr<BrowserGpuChannelHostFactory::EstablishRequest> |
| 75 BrowserGpuChannelHostFactory::EstablishRequest::Create( | 70 BrowserGpuChannelHostFactory::EstablishRequest::Create( |
| 76 int gpu_client_id, | 71 int gpu_client_id, |
| 77 uint64_t gpu_client_tracing_id, | 72 uint64_t gpu_client_tracing_id) { |
| 78 int gpu_host_id) { | |
| 79 scoped_refptr<EstablishRequest> establish_request = | 73 scoped_refptr<EstablishRequest> establish_request = |
| 80 new EstablishRequest(gpu_client_id, gpu_client_tracing_id, gpu_host_id); | 74 new EstablishRequest(gpu_client_id, gpu_client_tracing_id); |
| 81 scoped_refptr<base::SingleThreadTaskRunner> task_runner = | 75 scoped_refptr<base::SingleThreadTaskRunner> task_runner = |
| 82 BrowserThread::GetTaskRunnerForThread(BrowserThread::IO); | 76 BrowserThread::GetTaskRunnerForThread(BrowserThread::IO); |
| 83 // PostTask outside the constructor to ensure at least one reference exists. | 77 // PostTask outside the constructor to ensure at least one reference exists. |
| 84 task_runner->PostTask( | 78 task_runner->PostTask( |
| 85 FROM_HERE, | 79 FROM_HERE, |
| 86 base::Bind(&BrowserGpuChannelHostFactory::EstablishRequest::EstablishOnIO, | 80 base::Bind(&BrowserGpuChannelHostFactory::EstablishRequest::EstablishOnIO, |
| 87 establish_request)); | 81 establish_request)); |
| 88 return establish_request; | 82 return establish_request; |
| 89 } | 83 } |
| 90 | 84 |
| 91 BrowserGpuChannelHostFactory::EstablishRequest::EstablishRequest( | 85 BrowserGpuChannelHostFactory::EstablishRequest::EstablishRequest( |
| 92 int gpu_client_id, | 86 int gpu_client_id, |
| 93 uint64_t gpu_client_tracing_id, | 87 uint64_t gpu_client_tracing_id) |
| 94 int gpu_host_id) | |
| 95 : event_(base::WaitableEvent::ResetPolicy::AUTOMATIC, | 88 : event_(base::WaitableEvent::ResetPolicy::AUTOMATIC, |
| 96 base::WaitableEvent::InitialState::NOT_SIGNALED), | 89 base::WaitableEvent::InitialState::NOT_SIGNALED), |
| 97 gpu_client_id_(gpu_client_id), | 90 gpu_client_id_(gpu_client_id), |
| 98 gpu_client_tracing_id_(gpu_client_tracing_id), | 91 gpu_client_tracing_id_(gpu_client_tracing_id), |
| 99 gpu_host_id_(gpu_host_id), | |
| 100 reused_gpu_process_(false), | |
| 101 finished_(false), | 92 finished_(false), |
| 102 main_task_runner_(base::ThreadTaskRunnerHandle::Get()) {} | 93 main_task_runner_(base::ThreadTaskRunnerHandle::Get()) {} |
| 103 | 94 |
| 104 void BrowserGpuChannelHostFactory::EstablishRequest::EstablishOnIO() { | 95 void BrowserGpuChannelHostFactory::EstablishRequest::EstablishOnIO() { |
| 105 // TODO(pkasting): Remove ScopedTracker below once crbug.com/477117 is fixed. | 96 // TODO(pkasting): Remove ScopedTracker below once crbug.com/477117 is fixed. |
| 106 tracked_objects::ScopedTracker tracking_profile( | 97 tracked_objects::ScopedTracker tracking_profile( |
| 107 FROM_HERE_WITH_EXPLICIT_FUNCTION( | 98 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| 108 "477117 " | 99 "477117 " |
| 109 "BrowserGpuChannelHostFactory::EstablishRequest::EstablishOnIO")); | 100 "BrowserGpuChannelHostFactory::EstablishRequest::EstablishOnIO")); |
| 110 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_); | 101 GpuProcessHost* host = |
| 102 GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED); |
| 111 if (!host) { | 103 if (!host) { |
| 112 host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED); | 104 LOG(ERROR) << "Failed to launch GPU process."; |
| 113 if (!host) { | 105 FinishOnIO(); |
| 114 LOG(ERROR) << "Failed to launch GPU process."; | 106 return; |
| 115 FinishOnIO(); | |
| 116 return; | |
| 117 } | |
| 118 gpu_host_id_ = host->host_id(); | |
| 119 reused_gpu_process_ = false; | |
| 120 } else { | |
| 121 if (reused_gpu_process_) { | |
| 122 // We come here if we retried to establish the channel because of a | |
| 123 // failure in ChannelEstablishedOnIO, but we ended up with the same | |
| 124 // process ID, meaning the failure was not because of a channel error, | |
| 125 // but another reason. So fail now. | |
| 126 LOG(ERROR) << "Failed to create channel."; | |
| 127 FinishOnIO(); | |
| 128 return; | |
| 129 } | |
| 130 reused_gpu_process_ = true; | |
| 131 } | 107 } |
| 132 | 108 |
| 133 bool preempts = true; | 109 bool preempts = true; |
| 134 bool allow_view_command_buffers = true; | 110 bool allow_view_command_buffers = true; |
| 135 bool allow_real_time_streams = true; | 111 bool allow_real_time_streams = true; |
| 136 host->EstablishGpuChannel( | 112 host->EstablishGpuChannel( |
| 137 gpu_client_id_, gpu_client_tracing_id_, preempts, | 113 gpu_client_id_, gpu_client_tracing_id_, preempts, |
| 138 allow_view_command_buffers, allow_real_time_streams, | 114 allow_view_command_buffers, allow_real_time_streams, |
| 139 base::Bind( | 115 base::Bind( |
| 140 &BrowserGpuChannelHostFactory::EstablishRequest::OnEstablishedOnIO, | 116 &BrowserGpuChannelHostFactory::EstablishRequest::OnEstablishedOnIO, |
| 141 this)); | 117 this)); |
| 142 } | 118 } |
| 143 | 119 |
| 144 void BrowserGpuChannelHostFactory::EstablishRequest::OnEstablishedOnIO( | 120 void BrowserGpuChannelHostFactory::EstablishRequest::OnEstablishedOnIO( |
| 145 const IPC::ChannelHandle& channel_handle, | 121 const IPC::ChannelHandle& channel_handle, |
| 146 const gpu::GPUInfo& gpu_info) { | 122 const gpu::GPUInfo& gpu_info, |
| 147 if (!channel_handle.mojo_handle.is_valid() && reused_gpu_process_) { | 123 GpuProcessHost::EstablishChannelStatus status) { |
| 148 // We failed after re-using the GPU process, but it may have died in the | 124 if (!channel_handle.mojo_handle.is_valid() && |
| 149 // mean time. Retry to have a chance to create a fresh GPU process. | 125 status == GpuProcessHost::EstablishChannelStatus::GPU_HOST_INVALID) { |
| 150 DVLOG(1) << "Failed to create channel on existing GPU process. Trying to " | 126 DVLOG(1) << "Failed to create channel on existing GPU process. Trying to " |
| 151 "restart GPU process."; | 127 "restart GPU process."; |
| 152 EstablishOnIO(); | 128 EstablishOnIO(); |
| 153 } else { | 129 return; |
| 154 channel_handle_ = channel_handle; | |
| 155 gpu_info_ = gpu_info; | |
| 156 FinishOnIO(); | |
| 157 } | 130 } |
| 131 channel_handle_ = channel_handle; |
| 132 gpu_info_ = gpu_info; |
| 133 FinishOnIO(); |
| 158 } | 134 } |
| 159 | 135 |
| 160 void BrowserGpuChannelHostFactory::EstablishRequest::FinishOnIO() { | 136 void BrowserGpuChannelHostFactory::EstablishRequest::FinishOnIO() { |
| 161 event_.Signal(); | 137 event_.Signal(); |
| 162 main_task_runner_->PostTask( | 138 main_task_runner_->PostTask( |
| 163 FROM_HERE, | 139 FROM_HERE, |
| 164 base::Bind(&BrowserGpuChannelHostFactory::EstablishRequest::FinishOnMain, | 140 base::Bind(&BrowserGpuChannelHostFactory::EstablishRequest::FinishOnMain, |
| 165 this)); | 141 this)); |
| 166 } | 142 } |
| 167 | 143 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 | 203 |
| 228 BrowserGpuChannelHostFactory::BrowserGpuChannelHostFactory() | 204 BrowserGpuChannelHostFactory::BrowserGpuChannelHostFactory() |
| 229 : gpu_client_id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()), | 205 : gpu_client_id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()), |
| 230 gpu_client_tracing_id_( | 206 gpu_client_tracing_id_( |
| 231 memory_instrumentation::mojom::kServiceTracingProcessId), | 207 memory_instrumentation::mojom::kServiceTracingProcessId), |
| 232 shutdown_event_(new base::WaitableEvent( | 208 shutdown_event_(new base::WaitableEvent( |
| 233 base::WaitableEvent::ResetPolicy::MANUAL, | 209 base::WaitableEvent::ResetPolicy::MANUAL, |
| 234 base::WaitableEvent::InitialState::NOT_SIGNALED)), | 210 base::WaitableEvent::InitialState::NOT_SIGNALED)), |
| 235 gpu_memory_buffer_manager_( | 211 gpu_memory_buffer_manager_( |
| 236 new BrowserGpuMemoryBufferManager(gpu_client_id_, | 212 new BrowserGpuMemoryBufferManager(gpu_client_id_, |
| 237 gpu_client_tracing_id_)), | 213 gpu_client_tracing_id_)) { |
| 238 gpu_host_id_(0) { | |
| 239 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( | 214 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 240 switches::kDisableGpuShaderDiskCache)) { | 215 switches::kDisableGpuShaderDiskCache)) { |
| 241 DCHECK(GetContentClient()); | 216 DCHECK(GetContentClient()); |
| 242 base::FilePath cache_dir = | 217 base::FilePath cache_dir = |
| 243 GetContentClient()->browser()->GetShaderDiskCacheDirectory(); | 218 GetContentClient()->browser()->GetShaderDiskCacheDirectory(); |
| 244 if (!cache_dir.empty()) { | 219 if (!cache_dir.empty()) { |
| 245 GetIOThreadTaskRunner()->PostTask( | 220 GetIOThreadTaskRunner()->PostTask( |
| 246 FROM_HERE, | 221 FROM_HERE, |
| 247 base::Bind( | 222 base::Bind( |
| 248 &BrowserGpuChannelHostFactory::InitializeShaderDiskCacheOnIO, | 223 &BrowserGpuChannelHostFactory::InitializeShaderDiskCacheOnIO, |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 284 DCHECK(!service_manager::ServiceManagerIsRemote()); | 259 DCHECK(!service_manager::ServiceManagerIsRemote()); |
| 285 if (gpu_channel_.get() && gpu_channel_->IsLost()) { | 260 if (gpu_channel_.get() && gpu_channel_->IsLost()) { |
| 286 DCHECK(!pending_request_.get()); | 261 DCHECK(!pending_request_.get()); |
| 287 // Recreate the channel if it has been lost. | 262 // Recreate the channel if it has been lost. |
| 288 gpu_channel_->DestroyChannel(); | 263 gpu_channel_->DestroyChannel(); |
| 289 gpu_channel_ = NULL; | 264 gpu_channel_ = NULL; |
| 290 } | 265 } |
| 291 | 266 |
| 292 if (!gpu_channel_.get() && !pending_request_.get()) { | 267 if (!gpu_channel_.get() && !pending_request_.get()) { |
| 293 // We should only get here if the context was lost. | 268 // We should only get here if the context was lost. |
| 294 pending_request_ = EstablishRequest::Create( | 269 pending_request_ = |
| 295 gpu_client_id_, gpu_client_tracing_id_, gpu_host_id_); | 270 EstablishRequest::Create(gpu_client_id_, gpu_client_tracing_id_); |
| 296 } | 271 } |
| 297 | 272 |
| 298 if (!callback.is_null()) { | 273 if (!callback.is_null()) { |
| 299 if (gpu_channel_.get()) | 274 if (gpu_channel_.get()) |
| 300 callback.Run(gpu_channel_); | 275 callback.Run(gpu_channel_); |
| 301 else | 276 else |
| 302 established_callbacks_.push_back(callback); | 277 established_callbacks_.push_back(callback); |
| 303 } | 278 } |
| 304 } | 279 } |
| 305 | 280 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 342 // is fixed. | 317 // is fixed. |
| 343 tracked_objects::ScopedTracker tracking_profile1( | 318 tracked_objects::ScopedTracker tracking_profile1( |
| 344 FROM_HERE_WITH_EXPLICIT_FUNCTION( | 319 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| 345 "466866 BrowserGpuChannelHostFactory::GpuChannelEstablished1")); | 320 "466866 BrowserGpuChannelHostFactory::GpuChannelEstablished1")); |
| 346 GetContentClient()->SetGpuInfo(pending_request_->gpu_info()); | 321 GetContentClient()->SetGpuInfo(pending_request_->gpu_info()); |
| 347 gpu_channel_ = gpu::GpuChannelHost::Create( | 322 gpu_channel_ = gpu::GpuChannelHost::Create( |
| 348 this, gpu_client_id_, pending_request_->gpu_info(), | 323 this, gpu_client_id_, pending_request_->gpu_info(), |
| 349 pending_request_->channel_handle(), shutdown_event_.get(), | 324 pending_request_->channel_handle(), shutdown_event_.get(), |
| 350 gpu_memory_buffer_manager_.get()); | 325 gpu_memory_buffer_manager_.get()); |
| 351 } | 326 } |
| 352 gpu_host_id_ = pending_request_->gpu_host_id(); | |
| 353 pending_request_ = NULL; | 327 pending_request_ = NULL; |
| 354 | 328 |
| 355 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/466866 is | 329 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/466866 is |
| 356 // fixed. | 330 // fixed. |
| 357 tracked_objects::ScopedTracker tracking_profile2( | 331 tracked_objects::ScopedTracker tracking_profile2( |
| 358 FROM_HERE_WITH_EXPLICIT_FUNCTION( | 332 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| 359 "466866 BrowserGpuChannelHostFactory::GpuChannelEstablished2")); | 333 "466866 BrowserGpuChannelHostFactory::GpuChannelEstablished2")); |
| 360 | 334 |
| 361 std::vector<gpu::GpuChannelEstablishedCallback> established_callbacks; | 335 std::vector<gpu::GpuChannelEstablishedCallback> established_callbacks; |
| 362 established_callbacks_.swap(established_callbacks); | 336 established_callbacks_.swap(established_callbacks); |
| 363 for (auto& callback : established_callbacks) | 337 for (auto& callback : established_callbacks) |
| 364 callback.Run(gpu_channel_); | 338 callback.Run(gpu_channel_); |
| 365 } | 339 } |
| 366 | 340 |
| 367 // static | 341 // static |
| 368 void BrowserGpuChannelHostFactory::InitializeShaderDiskCacheOnIO( | 342 void BrowserGpuChannelHostFactory::InitializeShaderDiskCacheOnIO( |
| 369 int gpu_client_id, | 343 int gpu_client_id, |
| 370 const base::FilePath& cache_dir) { | 344 const base::FilePath& cache_dir) { |
| 371 GetShaderCacheFactorySingleton()->SetCacheInfo(gpu_client_id, cache_dir); | 345 GetShaderCacheFactorySingleton()->SetCacheInfo(gpu_client_id, cache_dir); |
| 372 } | 346 } |
| 373 | 347 |
| 374 } // namespace content | 348 } // namespace content |
| OLD | NEW |