OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/base_switches.h" | 7 #include "base/base_switches.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
11 #include "base/memory/ref_counted.h" | 11 #include "base/memory/ref_counted.h" |
12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
13 #include "base/process_util.h" | 13 #include "base/process_util.h" |
14 #include "base/string_piece.h" | 14 #include "base/string_piece.h" |
15 #include "base/threading/thread.h" | 15 #include "base/threading/thread.h" |
16 #include "content/browser/gpu/gpu_data_manager.h" | 16 #include "content/browser/gpu/gpu_data_manager.h" |
17 #include "content/browser/gpu/gpu_process_host_ui_shim.h" | 17 #include "content/browser/gpu/gpu_process_host_ui_shim.h" |
18 #include "content/browser/renderer_host/render_widget_host.h" | 18 #include "content/browser/renderer_host/render_widget_host.h" |
19 #include "content/browser/renderer_host/render_widget_host_view.h" | 19 #include "content/browser/renderer_host/render_widget_host_view.h" |
| 20 #include "content/common/child_process_host.h" |
20 #include "content/common/gpu/gpu_messages.h" | 21 #include "content/common/gpu/gpu_messages.h" |
21 #include "content/gpu/gpu_child_thread.h" | 22 #include "content/gpu/gpu_child_thread.h" |
22 #include "content/gpu/gpu_process.h" | 23 #include "content/gpu/gpu_process.h" |
23 #include "content/public/browser/browser_thread.h" | 24 #include "content/public/browser/browser_thread.h" |
24 #include "content/public/common/content_switches.h" | 25 #include "content/public/common/content_switches.h" |
25 #include "content/public/common/result_codes.h" | 26 #include "content/public/common/result_codes.h" |
26 #include "ipc/ipc_channel_handle.h" | 27 #include "ipc/ipc_channel_handle.h" |
27 #include "ipc/ipc_switches.h" | 28 #include "ipc/ipc_switches.h" |
28 #include "ui/gfx/gl/gl_context.h" | 29 #include "ui/gfx/gl/gl_context.h" |
29 #include "ui/gfx/gl/gl_implementation.h" | 30 #include "ui/gfx/gl/gl_implementation.h" |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 // GpuProcessHost is destroyed, which happens when the corresponding GPU | 273 // GpuProcessHost is destroyed, which happens when the corresponding GPU |
273 // process terminates or fails to launch. | 274 // process terminates or fails to launch. |
274 BrowserThread::PostTask( | 275 BrowserThread::PostTask( |
275 BrowserThread::UI, | 276 BrowserThread::UI, |
276 FROM_HERE, | 277 FROM_HERE, |
277 NewRunnableFunction(&GpuProcessHostUIShim::Create, host_id)); | 278 NewRunnableFunction(&GpuProcessHostUIShim::Create, host_id)); |
278 } | 279 } |
279 | 280 |
280 GpuProcessHost::~GpuProcessHost() { | 281 GpuProcessHost::~GpuProcessHost() { |
281 DCHECK(CalledOnValidThread()); | 282 DCHECK(CalledOnValidThread()); |
| 283 |
| 284 SendOutstandingReplies(); |
| 285 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents", |
| 286 DIED_FIRST_TIME + g_gpu_crash_count, |
| 287 GPU_PROCESS_LIFETIME_EVENT_MAX); |
| 288 |
| 289 int exit_code; |
| 290 base::TerminationStatus status = GetChildTerminationStatus(&exit_code); |
| 291 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessTerminationStatus", |
| 292 status, |
| 293 base::TERMINATION_STATUS_MAX_ENUM); |
| 294 |
| 295 if (status == base::TERMINATION_STATUS_NORMAL_TERMINATION || |
| 296 status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION) { |
| 297 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessExitCode", |
| 298 exit_code, |
| 299 content::RESULT_CODE_LAST_CODE); |
| 300 } |
| 301 |
282 #if defined(OS_WIN) | 302 #if defined(OS_WIN) |
283 if (gpu_process_) | 303 if (gpu_process_) |
284 CloseHandle(gpu_process_); | 304 CloseHandle(gpu_process_); |
285 #endif | 305 #endif |
286 | 306 |
287 // In case we never started, clean up. | 307 // In case we never started, clean up. |
288 while (!queued_messages_.empty()) { | 308 while (!queued_messages_.empty()) { |
289 delete queued_messages_.front(); | 309 delete queued_messages_.front(); |
290 queued_messages_.pop(); | 310 queued_messages_.pop(); |
291 } | 311 } |
292 | 312 |
293 g_hosts_by_id.Pointer()->Remove(host_id_); | 313 g_hosts_by_id.Pointer()->Remove(host_id_); |
294 | 314 |
295 BrowserThread::PostTask(BrowserThread::UI, | 315 BrowserThread::PostTask(BrowserThread::UI, |
296 FROM_HERE, | 316 FROM_HERE, |
297 NewRunnableFunction(GpuProcessHostUIShim::Destroy, | 317 NewRunnableFunction(GpuProcessHostUIShim::Destroy, |
298 host_id_)); | 318 host_id_)); |
299 } | 319 } |
300 | 320 |
301 bool GpuProcessHost::Init() { | 321 bool GpuProcessHost::Init() { |
302 if (!CreateChannel()) | 322 if (!child_process_host()->CreateChannel()) |
303 return false; | 323 return false; |
304 | 324 |
305 if (in_process_) { | 325 if (in_process_) { |
306 CommandLine::ForCurrentProcess()->AppendSwitch( | 326 CommandLine::ForCurrentProcess()->AppendSwitch( |
307 switches::kDisableGpuWatchdog); | 327 switches::kDisableGpuWatchdog); |
308 | 328 |
309 in_process_gpu_thread_.reset(new GpuMainThread(channel_id())); | 329 in_process_gpu_thread_.reset(new GpuMainThread( |
| 330 child_process_host()->channel_id())); |
310 | 331 |
311 base::Thread::Options options; | 332 base::Thread::Options options; |
312 #if defined(OS_WIN) | 333 #if defined(OS_WIN) |
313 // On Windows the GPU thread needs to pump the compositor child window's | 334 // On Windows the GPU thread needs to pump the compositor child window's |
314 // message loop. TODO(apatrick): make this an IO thread if / when we get rid | 335 // message loop. TODO(apatrick): make this an IO thread if / when we get rid |
315 // of this child window. Unfortunately it might always be necessary for | 336 // of this child window. Unfortunately it might always be necessary for |
316 // Windows XP because we cannot share the backing store textures between | 337 // Windows XP because we cannot share the backing store textures between |
317 // processes. | 338 // processes. |
318 options.message_loop_type = MessageLoop::TYPE_UI; | 339 options.message_loop_type = MessageLoop::TYPE_UI; |
319 #else | 340 #else |
(...skipping 10 matching lines...) Expand all Loading... |
330 | 351 |
331 void GpuProcessHost::RouteOnUIThread(const IPC::Message& message) { | 352 void GpuProcessHost::RouteOnUIThread(const IPC::Message& message) { |
332 BrowserThread::PostTask( | 353 BrowserThread::PostTask( |
333 BrowserThread::UI, | 354 BrowserThread::UI, |
334 FROM_HERE, | 355 FROM_HERE, |
335 new RouteToGpuProcessHostUIShimTask(host_id_, message)); | 356 new RouteToGpuProcessHostUIShimTask(host_id_, message)); |
336 } | 357 } |
337 | 358 |
338 bool GpuProcessHost::Send(IPC::Message* msg) { | 359 bool GpuProcessHost::Send(IPC::Message* msg) { |
339 DCHECK(CalledOnValidThread()); | 360 DCHECK(CalledOnValidThread()); |
340 if (opening_channel()) { | 361 if (child_process_host()->opening_channel()) { |
341 queued_messages_.push(msg); | 362 queued_messages_.push(msg); |
342 return true; | 363 return true; |
343 } | 364 } |
344 | 365 |
345 return BrowserChildProcessHost::Send(msg); | 366 return BrowserChildProcessHost::Send(msg); |
346 } | 367 } |
347 | 368 |
348 bool GpuProcessHost::OnMessageReceived(const IPC::Message& message) { | 369 bool GpuProcessHost::OnMessageReceived(const IPC::Message& message) { |
349 DCHECK(CalledOnValidThread()); | 370 DCHECK(CalledOnValidThread()); |
350 IPC_BEGIN_MESSAGE_MAP(GpuProcessHost, message) | 371 IPC_BEGIN_MESSAGE_MAP(GpuProcessHost, message) |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
477 SurfaceRefMap::iterator it = surface_refs_.find(view_id); | 498 SurfaceRefMap::iterator it = surface_refs_.find(view_id); |
478 if (it != surface_refs_.end()) | 499 if (it != surface_refs_.end()) |
479 surface_refs_.erase(it); | 500 surface_refs_.erase(it); |
480 #endif // defined(TOOLKIT_USES_GTK) | 501 #endif // defined(TOOLKIT_USES_GTK) |
481 } | 502 } |
482 | 503 |
483 void GpuProcessHost::OnGraphicsInfoCollected(const content::GPUInfo& gpu_info) { | 504 void GpuProcessHost::OnGraphicsInfoCollected(const content::GPUInfo& gpu_info) { |
484 GpuDataManager::GetInstance()->UpdateGpuInfo(gpu_info); | 505 GpuDataManager::GetInstance()->UpdateGpuInfo(gpu_info); |
485 } | 506 } |
486 | 507 |
487 bool GpuProcessHost::CanShutdown() { | |
488 return true; | |
489 } | |
490 | |
491 void GpuProcessHost::OnProcessLaunched() { | 508 void GpuProcessHost::OnProcessLaunched() { |
492 // Send the GPU process handle to the UI thread before it has to | 509 // Send the GPU process handle to the UI thread before it has to |
493 // respond to any requests to establish a GPU channel. The response | 510 // respond to any requests to establish a GPU channel. The response |
494 // to such requests require that the GPU process handle be known. | 511 // to such requests require that the GPU process handle be known. |
495 | 512 |
496 TRACE_EVENT0("test_gpu", "GpuProcessLaunched"); | 513 TRACE_EVENT0("test_gpu", "GpuProcessLaunched"); |
497 | 514 |
498 base::ProcessHandle child_handle = in_process_ ? | 515 base::ProcessHandle child_handle = in_process_ ? |
499 base::GetCurrentProcessHandle() : handle(); | 516 base::GetCurrentProcessHandle() : handle(); |
500 | 517 |
501 #if defined(OS_WIN) | 518 #if defined(OS_WIN) |
502 DuplicateHandle(base::GetCurrentProcessHandle(), | 519 DuplicateHandle(base::GetCurrentProcessHandle(), |
503 child_handle, | 520 child_handle, |
504 base::GetCurrentProcessHandle(), | 521 base::GetCurrentProcessHandle(), |
505 &gpu_process_, | 522 &gpu_process_, |
506 PROCESS_DUP_HANDLE, | 523 PROCESS_DUP_HANDLE, |
507 FALSE, | 524 FALSE, |
508 0); | 525 0); |
509 #else | 526 #else |
510 gpu_process_ = child_handle; | 527 gpu_process_ = child_handle; |
511 #endif | 528 #endif |
512 } | 529 } |
513 | 530 |
514 void GpuProcessHost::OnChildDied() { | |
515 SendOutstandingReplies(); | |
516 // Located in OnChildDied because OnProcessCrashed suffers from a race | |
517 // condition on Linux. | |
518 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents", | |
519 DIED_FIRST_TIME + g_gpu_crash_count, | |
520 GPU_PROCESS_LIFETIME_EVENT_MAX); | |
521 | |
522 int exit_code; | |
523 base::TerminationStatus status = GetChildTerminationStatus(&exit_code); | |
524 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessTerminationStatus", | |
525 status, | |
526 base::TERMINATION_STATUS_MAX_ENUM); | |
527 | |
528 if (status == base::TERMINATION_STATUS_NORMAL_TERMINATION || | |
529 status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION) { | |
530 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessExitCode", | |
531 exit_code, | |
532 content::RESULT_CODE_LAST_CODE); | |
533 } | |
534 | |
535 ChildProcessHost::OnChildDied(); | |
536 } | |
537 | |
538 void GpuProcessHost::OnProcessCrashed(int exit_code) { | 531 void GpuProcessHost::OnProcessCrashed(int exit_code) { |
539 SendOutstandingReplies(); | 532 SendOutstandingReplies(); |
540 if (++g_gpu_crash_count >= kGpuMaxCrashCount) { | 533 if (++g_gpu_crash_count >= kGpuMaxCrashCount) { |
541 // The gpu process is too unstable to use. Disable it for current session. | 534 // The gpu process is too unstable to use. Disable it for current session. |
542 gpu_enabled_ = false; | 535 gpu_enabled_ = false; |
543 } | 536 } |
544 BrowserChildProcessHost::OnProcessCrashed(exit_code); | 537 BrowserChildProcessHost::OnProcessCrashed(exit_code); |
545 } | 538 } |
546 | 539 |
547 bool GpuProcessHost::software_rendering() { | 540 bool GpuProcessHost::software_rendering() { |
(...skipping 18 matching lines...) Expand all Loading... |
566 #else | 559 #else |
567 int child_flags = ChildProcessHost::CHILD_NORMAL; | 560 int child_flags = ChildProcessHost::CHILD_NORMAL; |
568 #endif | 561 #endif |
569 | 562 |
570 FilePath exe_path = ChildProcessHost::GetChildPath(child_flags); | 563 FilePath exe_path = ChildProcessHost::GetChildPath(child_flags); |
571 if (exe_path.empty()) | 564 if (exe_path.empty()) |
572 return false; | 565 return false; |
573 | 566 |
574 CommandLine* cmd_line = new CommandLine(exe_path); | 567 CommandLine* cmd_line = new CommandLine(exe_path); |
575 cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kGpuProcess); | 568 cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kGpuProcess); |
576 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id()); | 569 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, |
| 570 child_process_host()->channel_id()); |
577 | 571 |
578 // Propagate relevant command line switches. | 572 // Propagate relevant command line switches. |
579 static const char* const kSwitchNames[] = { | 573 static const char* const kSwitchNames[] = { |
580 switches::kDisableBreakpad, | 574 switches::kDisableBreakpad, |
581 switches::kDisableGLMultisampling, | 575 switches::kDisableGLMultisampling, |
582 switches::kDisableGpuDriverBugWorkarounds, | 576 switches::kDisableGpuDriverBugWorkarounds, |
583 switches::kDisableGpuSandbox, | 577 switches::kDisableGpuSandbox, |
584 switches::kDisableGpuVsync, | 578 switches::kDisableGpuVsync, |
585 switches::kDisableGpuWatchdog, | 579 switches::kDisableGpuWatchdog, |
586 switches::kDisableLogging, | 580 switches::kDisableLogging, |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
647 scoped_ptr<EstablishChannelCallback> wrapped_callback(callback); | 641 scoped_ptr<EstablishChannelCallback> wrapped_callback(callback); |
648 wrapped_callback->Run(channel_handle, renderer_process_for_gpu, gpu_info); | 642 wrapped_callback->Run(channel_handle, renderer_process_for_gpu, gpu_info); |
649 } | 643 } |
650 | 644 |
651 void GpuProcessHost::CreateCommandBufferError( | 645 void GpuProcessHost::CreateCommandBufferError( |
652 CreateCommandBufferCallback* callback, int32 route_id) { | 646 CreateCommandBufferCallback* callback, int32 route_id) { |
653 scoped_ptr<GpuProcessHost::CreateCommandBufferCallback> | 647 scoped_ptr<GpuProcessHost::CreateCommandBufferCallback> |
654 wrapped_callback(callback); | 648 wrapped_callback(callback); |
655 callback->Run(route_id); | 649 callback->Run(route_id); |
656 } | 650 } |
OLD | NEW |