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/gpu_process_host.h" | 5 #include "content/browser/gpu/gpu_process_host.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/base_switches.h" | 9 #include "base/base_switches.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
11 #include "base/debug/trace_event.h" | 11 #include "base/debug/trace_event.h" |
12 #include "base/lazy_instance.h" | 12 #include "base/lazy_instance.h" |
13 #include "base/memory/ref_counted.h" | 13 #include "base/memory/ref_counted.h" |
14 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
15 #include "base/process_util.h" | 15 #include "base/process_util.h" |
16 #include "base/string_piece.h" | 16 #include "base/string_piece.h" |
17 #include "base/threading/thread.h" | 17 #include "base/threading/thread.h" |
| 18 #include "content/browser/browser_child_process_host.h" |
18 #include "content/browser/gpu/gpu_data_manager.h" | 19 #include "content/browser/gpu/gpu_data_manager.h" |
19 #include "content/browser/gpu/gpu_process_host_ui_shim.h" | 20 #include "content/browser/gpu/gpu_process_host_ui_shim.h" |
20 #include "content/browser/renderer_host/render_widget_host.h" | 21 #include "content/browser/renderer_host/render_widget_host.h" |
21 #include "content/browser/renderer_host/render_widget_host_view.h" | 22 #include "content/browser/renderer_host/render_widget_host_view.h" |
22 #include "content/common/child_process_host_impl.h" | 23 #include "content/common/child_process_host_impl.h" |
23 #include "content/common/gpu/gpu_messages.h" | 24 #include "content/common/gpu/gpu_messages.h" |
24 #include "content/gpu/gpu_child_thread.h" | 25 #include "content/gpu/gpu_child_thread.h" |
25 #include "content/gpu/gpu_process.h" | 26 #include "content/gpu/gpu_process.h" |
26 #include "content/public/browser/browser_thread.h" | 27 #include "content/public/browser/browser_thread.h" |
27 #include "content/public/common/content_switches.h" | 28 #include "content/public/common/content_switches.h" |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 | 154 |
154 private: | 155 private: |
155 std::string channel_id_; | 156 std::string channel_id_; |
156 // Deleted in CleanUp() on the gpu thread, so don't use smart pointers. | 157 // Deleted in CleanUp() on the gpu thread, so don't use smart pointers. |
157 GpuProcess* gpu_process_; | 158 GpuProcess* gpu_process_; |
158 GpuChildThread* child_thread_; | 159 GpuChildThread* child_thread_; |
159 | 160 |
160 DISALLOW_COPY_AND_ASSIGN(GpuMainThread); | 161 DISALLOW_COPY_AND_ASSIGN(GpuMainThread); |
161 }; | 162 }; |
162 | 163 |
163 static bool HostIsValid(GpuProcessHost* host) { | 164 // static |
| 165 bool GpuProcessHost::HostIsValid(GpuProcessHost* host) { |
164 if (!host) | 166 if (!host) |
165 return false; | 167 return false; |
166 | 168 |
167 // Check if the GPU process has died and the host is about to be destroyed. | 169 // Check if the GPU process has died and the host is about to be destroyed. |
168 if (host->disconnect_was_alive()) | 170 if (host->process_->disconnect_was_alive()) |
169 return false; | 171 return false; |
170 | 172 |
171 // The Gpu process is invalid if it's not using software, the card is | 173 // The Gpu process is invalid if it's not using software, the card is |
172 // blacklisted, and we can kill it and start over. | 174 // blacklisted, and we can kill it and start over. |
173 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) || | 175 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) || |
174 CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU) || | 176 CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU) || |
175 host->software_rendering() || | 177 host->software_rendering() || |
176 !GpuDataManager::GetInstance()->software_rendering()) { | 178 !GpuDataManager::GetInstance()->software_rendering()) { |
177 return true; | 179 return true; |
178 } | 180 } |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 return NULL; | 240 return NULL; |
239 | 241 |
240 GpuProcessHost *host = g_hosts_by_id.Pointer()->Lookup(host_id); | 242 GpuProcessHost *host = g_hosts_by_id.Pointer()->Lookup(host_id); |
241 if (HostIsValid(host)) | 243 if (HostIsValid(host)) |
242 return host; | 244 return host; |
243 | 245 |
244 return NULL; | 246 return NULL; |
245 } | 247 } |
246 | 248 |
247 GpuProcessHost::GpuProcessHost(int host_id) | 249 GpuProcessHost::GpuProcessHost(int host_id) |
248 : BrowserChildProcessHost(content::PROCESS_TYPE_GPU), | 250 : host_id_(host_id), |
249 host_id_(host_id), | |
250 gpu_process_(base::kNullProcessHandle), | 251 gpu_process_(base::kNullProcessHandle), |
251 in_process_(false), | 252 in_process_(false), |
252 software_rendering_(false) { | 253 software_rendering_(false) { |
253 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) || | 254 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) || |
254 CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU)) | 255 CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU)) |
255 in_process_ = true; | 256 in_process_ = true; |
256 | 257 |
257 // If the 'single GPU process' policy ever changes, we still want to maintain | 258 // If the 'single GPU process' policy ever changes, we still want to maintain |
258 // it for 'gpu thread' mode and only create one instance of host and thread. | 259 // it for 'gpu thread' mode and only create one instance of host and thread. |
259 DCHECK(!in_process_ || g_hosts_by_id.Pointer()->IsEmpty()); | 260 DCHECK(!in_process_ || g_hosts_by_id.Pointer()->IsEmpty()); |
260 | 261 |
261 g_hosts_by_id.Pointer()->AddWithID(this, host_id_); | 262 g_hosts_by_id.Pointer()->AddWithID(this, host_id_); |
262 | 263 |
263 // Post a task to create the corresponding GpuProcessHostUIShim. The | 264 // Post a task to create the corresponding GpuProcessHostUIShim. The |
264 // GpuProcessHostUIShim will be destroyed if either the browser exits, | 265 // GpuProcessHostUIShim will be destroyed if either the browser exits, |
265 // in which case it calls GpuProcessHostUIShim::DestroyAll, or the | 266 // in which case it calls GpuProcessHostUIShim::DestroyAll, or the |
266 // GpuProcessHost is destroyed, which happens when the corresponding GPU | 267 // GpuProcessHost is destroyed, which happens when the corresponding GPU |
267 // process terminates or fails to launch. | 268 // process terminates or fails to launch. |
268 BrowserThread::PostTask( | 269 BrowserThread::PostTask( |
269 BrowserThread::UI, | 270 BrowserThread::UI, |
270 FROM_HERE, | 271 FROM_HERE, |
271 base::Bind(base::IgnoreResult(&GpuProcessHostUIShim::Create), host_id)); | 272 base::Bind(base::IgnoreResult(&GpuProcessHostUIShim::Create), host_id)); |
| 273 |
| 274 process_.reset(new BrowserChildProcessHost(content::PROCESS_TYPE_GPU, this)); |
272 } | 275 } |
273 | 276 |
274 GpuProcessHost::~GpuProcessHost() { | 277 GpuProcessHost::~GpuProcessHost() { |
275 DCHECK(CalledOnValidThread()); | 278 DCHECK(CalledOnValidThread()); |
276 | 279 |
277 SendOutstandingReplies(); | 280 SendOutstandingReplies(); |
278 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents", | 281 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents", |
279 DIED_FIRST_TIME + g_gpu_crash_count, | 282 DIED_FIRST_TIME + g_gpu_crash_count, |
280 GPU_PROCESS_LIFETIME_EVENT_MAX); | 283 GPU_PROCESS_LIFETIME_EVENT_MAX); |
281 | 284 |
282 int exit_code; | 285 int exit_code; |
283 base::TerminationStatus status = GetChildTerminationStatus(&exit_code); | 286 base::TerminationStatus status = process_->GetTerminationStatus(&exit_code); |
284 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessTerminationStatus", | 287 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessTerminationStatus", |
285 status, | 288 status, |
286 base::TERMINATION_STATUS_MAX_ENUM); | 289 base::TERMINATION_STATUS_MAX_ENUM); |
287 | 290 |
288 if (status == base::TERMINATION_STATUS_NORMAL_TERMINATION || | 291 if (status == base::TERMINATION_STATUS_NORMAL_TERMINATION || |
289 status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION) { | 292 status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION) { |
290 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessExitCode", | 293 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessExitCode", |
291 exit_code, | 294 exit_code, |
292 content::RESULT_CODE_LAST_CODE); | 295 content::RESULT_CODE_LAST_CODE); |
293 } | 296 } |
(...skipping 10 matching lines...) Expand all Loading... |
304 } | 307 } |
305 | 308 |
306 g_hosts_by_id.Pointer()->Remove(host_id_); | 309 g_hosts_by_id.Pointer()->Remove(host_id_); |
307 | 310 |
308 BrowserThread::PostTask(BrowserThread::UI, | 311 BrowserThread::PostTask(BrowserThread::UI, |
309 FROM_HERE, | 312 FROM_HERE, |
310 base::Bind(&GpuProcessHostUIShim::Destroy, host_id_)); | 313 base::Bind(&GpuProcessHostUIShim::Destroy, host_id_)); |
311 } | 314 } |
312 | 315 |
313 bool GpuProcessHost::Init() { | 316 bool GpuProcessHost::Init() { |
314 std::string channel_id = child_process_host()->CreateChannel(); | 317 std::string channel_id = process_->GetHost()->CreateChannel(); |
315 if (channel_id.empty()) | 318 if (channel_id.empty()) |
316 return false; | 319 return false; |
317 | 320 |
318 if (in_process_) { | 321 if (in_process_) { |
319 CommandLine::ForCurrentProcess()->AppendSwitch( | 322 CommandLine::ForCurrentProcess()->AppendSwitch( |
320 switches::kDisableGpuWatchdog); | 323 switches::kDisableGpuWatchdog); |
321 | 324 |
322 in_process_gpu_thread_.reset(new GpuMainThread(channel_id)); | 325 in_process_gpu_thread_.reset(new GpuMainThread(channel_id)); |
323 | 326 |
324 base::Thread::Options options; | 327 base::Thread::Options options; |
(...skipping 18 matching lines...) Expand all Loading... |
343 | 346 |
344 void GpuProcessHost::RouteOnUIThread(const IPC::Message& message) { | 347 void GpuProcessHost::RouteOnUIThread(const IPC::Message& message) { |
345 BrowserThread::PostTask( | 348 BrowserThread::PostTask( |
346 BrowserThread::UI, | 349 BrowserThread::UI, |
347 FROM_HERE, | 350 FROM_HERE, |
348 base::Bind(&RouteToGpuProcessHostUIShimTask, host_id_, message)); | 351 base::Bind(&RouteToGpuProcessHostUIShimTask, host_id_, message)); |
349 } | 352 } |
350 | 353 |
351 bool GpuProcessHost::Send(IPC::Message* msg) { | 354 bool GpuProcessHost::Send(IPC::Message* msg) { |
352 DCHECK(CalledOnValidThread()); | 355 DCHECK(CalledOnValidThread()); |
353 if (child_process_host()->IsChannelOpening()) { | 356 if (process_->GetHost()->IsChannelOpening()) { |
354 queued_messages_.push(msg); | 357 queued_messages_.push(msg); |
355 return true; | 358 return true; |
356 } | 359 } |
357 | 360 |
358 return BrowserChildProcessHost::Send(msg); | 361 return process_->Send(msg); |
359 } | 362 } |
360 | 363 |
361 bool GpuProcessHost::OnMessageReceived(const IPC::Message& message) { | 364 bool GpuProcessHost::OnMessageReceived(const IPC::Message& message) { |
362 DCHECK(CalledOnValidThread()); | 365 DCHECK(CalledOnValidThread()); |
363 IPC_BEGIN_MESSAGE_MAP(GpuProcessHost, message) | 366 IPC_BEGIN_MESSAGE_MAP(GpuProcessHost, message) |
364 IPC_MESSAGE_HANDLER(GpuHostMsg_ChannelEstablished, OnChannelEstablished) | 367 IPC_MESSAGE_HANDLER(GpuHostMsg_ChannelEstablished, OnChannelEstablished) |
365 IPC_MESSAGE_HANDLER(GpuHostMsg_CommandBufferCreated, OnCommandBufferCreated) | 368 IPC_MESSAGE_HANDLER(GpuHostMsg_CommandBufferCreated, OnCommandBufferCreated) |
366 IPC_MESSAGE_HANDLER(GpuHostMsg_DestroyCommandBuffer, OnDestroyCommandBuffer) | 369 IPC_MESSAGE_HANDLER(GpuHostMsg_DestroyCommandBuffer, OnDestroyCommandBuffer) |
367 IPC_MESSAGE_UNHANDLED(RouteOnUIThread(message)) | 370 IPC_MESSAGE_UNHANDLED(RouteOnUIThread(message)) |
368 IPC_END_MESSAGE_MAP() | 371 IPC_END_MESSAGE_MAP() |
369 | 372 |
370 return true; | 373 return true; |
371 } | 374 } |
372 | 375 |
373 void GpuProcessHost::OnChannelConnected(int32 peer_pid) { | 376 void GpuProcessHost::OnChannelConnected(int32 peer_pid) { |
374 BrowserChildProcessHost::OnChannelConnected(peer_pid); | |
375 while (!queued_messages_.empty()) { | 377 while (!queued_messages_.empty()) { |
376 Send(queued_messages_.front()); | 378 Send(queued_messages_.front()); |
377 queued_messages_.pop(); | 379 queued_messages_.pop(); |
378 } | 380 } |
379 } | 381 } |
380 | 382 |
381 void GpuProcessHost::EstablishGpuChannel( | 383 void GpuProcessHost::EstablishGpuChannel( |
382 int client_id, | 384 int client_id, |
383 const EstablishChannelCallback& callback) { | 385 const EstablishChannelCallback& callback) { |
384 DCHECK(CalledOnValidThread()); | 386 DCHECK(CalledOnValidThread()); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
482 surface_refs_.erase(it); | 484 surface_refs_.erase(it); |
483 #endif // defined(TOOLKIT_USES_GTK) | 485 #endif // defined(TOOLKIT_USES_GTK) |
484 } | 486 } |
485 | 487 |
486 void GpuProcessHost::OnProcessLaunched() { | 488 void GpuProcessHost::OnProcessLaunched() { |
487 // Send the GPU process handle to the UI thread before it has to | 489 // Send the GPU process handle to the UI thread before it has to |
488 // respond to any requests to establish a GPU channel. The response | 490 // respond to any requests to establish a GPU channel. The response |
489 // to such requests require that the GPU process handle be known. | 491 // to such requests require that the GPU process handle be known. |
490 | 492 |
491 base::ProcessHandle child_handle = in_process_ ? | 493 base::ProcessHandle child_handle = in_process_ ? |
492 base::GetCurrentProcessHandle() : data().handle; | 494 base::GetCurrentProcessHandle() : process_->GetData().handle; |
493 | 495 |
494 #if defined(OS_WIN) | 496 #if defined(OS_WIN) |
495 DuplicateHandle(base::GetCurrentProcessHandle(), | 497 DuplicateHandle(base::GetCurrentProcessHandle(), |
496 child_handle, | 498 child_handle, |
497 base::GetCurrentProcessHandle(), | 499 base::GetCurrentProcessHandle(), |
498 &gpu_process_, | 500 &gpu_process_, |
499 PROCESS_DUP_HANDLE, | 501 PROCESS_DUP_HANDLE, |
500 FALSE, | 502 FALSE, |
501 0); | 503 0); |
502 #else | 504 #else |
503 gpu_process_ = child_handle; | 505 gpu_process_ = child_handle; |
504 #endif | 506 #endif |
505 } | 507 } |
506 | 508 |
507 void GpuProcessHost::OnProcessCrashed(int exit_code) { | 509 void GpuProcessHost::OnProcessCrashed(int exit_code) { |
508 SendOutstandingReplies(); | 510 SendOutstandingReplies(); |
509 if (++g_gpu_crash_count >= kGpuMaxCrashCount) { | 511 if (++g_gpu_crash_count >= kGpuMaxCrashCount) { |
510 // The gpu process is too unstable to use. Disable it for current session. | 512 // The gpu process is too unstable to use. Disable it for current session. |
511 gpu_enabled_ = false; | 513 gpu_enabled_ = false; |
512 } | 514 } |
513 BrowserChildProcessHost::OnProcessCrashed(exit_code); | |
514 } | 515 } |
515 | 516 |
516 bool GpuProcessHost::software_rendering() { | 517 bool GpuProcessHost::software_rendering() { |
517 return software_rendering_; | 518 return software_rendering_; |
518 } | 519 } |
519 | 520 |
520 void GpuProcessHost::ForceShutdown() { | 521 void GpuProcessHost::ForceShutdown() { |
521 g_hosts_by_id.Pointer()->Remove(host_id_); | 522 g_hosts_by_id.Pointer()->Remove(host_id_); |
522 BrowserChildProcessHost::ForceShutdown(); | 523 process_->ForceShutdown(); |
523 } | 524 } |
524 | 525 |
525 bool GpuProcessHost::LaunchGpuProcess(const std::string& channel_id) { | 526 bool GpuProcessHost::LaunchGpuProcess(const std::string& channel_id) { |
526 if (!gpu_enabled_ || g_gpu_crash_count >= kGpuMaxCrashCount) { | 527 if (!gpu_enabled_ || g_gpu_crash_count >= kGpuMaxCrashCount) { |
527 SendOutstandingReplies(); | 528 SendOutstandingReplies(); |
528 gpu_enabled_ = false; | 529 gpu_enabled_ = false; |
529 return false; | 530 return false; |
530 } | 531 } |
531 | 532 |
532 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); | 533 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
582 GpuDataManager::GetInstance()->AppendGpuCommandLine(cmd_line); | 583 GpuDataManager::GetInstance()->AppendGpuCommandLine(cmd_line); |
583 | 584 |
584 if (cmd_line->HasSwitch(switches::kUseGL)) | 585 if (cmd_line->HasSwitch(switches::kUseGL)) |
585 software_rendering_ = | 586 software_rendering_ = |
586 (cmd_line->GetSwitchValueASCII(switches::kUseGL) == "swiftshader"); | 587 (cmd_line->GetSwitchValueASCII(switches::kUseGL) == "swiftshader"); |
587 | 588 |
588 // If specified, prepend a launcher program to the command line. | 589 // If specified, prepend a launcher program to the command line. |
589 if (!gpu_launcher.empty()) | 590 if (!gpu_launcher.empty()) |
590 cmd_line->PrependWrapper(gpu_launcher); | 591 cmd_line->PrependWrapper(gpu_launcher); |
591 | 592 |
592 Launch( | 593 process_->Launch( |
593 #if defined(OS_WIN) | 594 #if defined(OS_WIN) |
594 FilePath(), | 595 FilePath(), |
595 #elif defined(OS_POSIX) | 596 #elif defined(OS_POSIX) |
596 false, // Never use the zygote (GPU plugin can't be sandboxed). | 597 false, // Never use the zygote (GPU plugin can't be sandboxed). |
597 base::environment_vector(), | 598 base::environment_vector(), |
598 #endif | 599 #endif |
599 cmd_line); | 600 cmd_line); |
600 | 601 |
601 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents", | 602 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents", |
602 LAUNCHED, GPU_PROCESS_LIFETIME_EVENT_MAX); | 603 LAUNCHED, GPU_PROCESS_LIFETIME_EVENT_MAX); |
(...skipping 17 matching lines...) Expand all Loading... |
620 const IPC::ChannelHandle& channel_handle, | 621 const IPC::ChannelHandle& channel_handle, |
621 base::ProcessHandle renderer_process_for_gpu, | 622 base::ProcessHandle renderer_process_for_gpu, |
622 const content::GPUInfo& gpu_info) { | 623 const content::GPUInfo& gpu_info) { |
623 callback.Run(channel_handle, renderer_process_for_gpu, gpu_info); | 624 callback.Run(channel_handle, renderer_process_for_gpu, gpu_info); |
624 } | 625 } |
625 | 626 |
626 void GpuProcessHost::CreateCommandBufferError( | 627 void GpuProcessHost::CreateCommandBufferError( |
627 const CreateCommandBufferCallback& callback, int32 route_id) { | 628 const CreateCommandBufferCallback& callback, int32 route_id) { |
628 callback.Run(route_id); | 629 callback.Run(route_id); |
629 } | 630 } |
OLD | NEW |