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