| 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" |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 | 162 |
| 163 private: | 163 private: |
| 164 std::string channel_id_; | 164 std::string channel_id_; |
| 165 // Deleted in CleanUp() on the gpu thread, so don't use smart pointers. | 165 // Deleted in CleanUp() on the gpu thread, so don't use smart pointers. |
| 166 GpuProcess* gpu_process_; | 166 GpuProcess* gpu_process_; |
| 167 GpuChildThread* child_thread_; | 167 GpuChildThread* child_thread_; |
| 168 | 168 |
| 169 DISALLOW_COPY_AND_ASSIGN(GpuMainThread); | 169 DISALLOW_COPY_AND_ASSIGN(GpuMainThread); |
| 170 }; | 170 }; |
| 171 | 171 |
| 172 static bool HostIsValid(int host_id, GpuProcessHost* host) { |
| 173 if (!host) |
| 174 return false; |
| 175 |
| 176 // The Gpu process is invalid if it's not using software, the card is |
| 177 // blacklisted, and we can kill it and start over. |
| 178 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) || |
| 179 CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU) || |
| 180 host->SoftwareRendering() || |
| 181 !GpuDataManager::GetInstance()->SoftwareRendering()) { |
| 182 return true; |
| 183 } |
| 184 |
| 185 host->Send(new GpuMsg_Crash()); |
| 186 g_hosts_by_id.Pointer()->Remove(host_id); |
| 187 return false; |
| 188 } |
| 189 |
| 172 // static | 190 // static |
| 173 GpuProcessHost* GpuProcessHost::GetForRenderer( | 191 GpuProcessHost* GpuProcessHost::GetForRenderer( |
| 174 int renderer_id, content::CauseForGpuLaunch cause) { | 192 int renderer_id, content::CauseForGpuLaunch cause) { |
| 175 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 193 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 176 | 194 |
| 177 // Don't grant further access to GPU if it is not allowed. | 195 // Don't grant further access to GPU if it is not allowed. |
| 178 GpuDataManager* gpu_data_manager = GpuDataManager::GetInstance(); | 196 GpuDataManager* gpu_data_manager = GpuDataManager::GetInstance(); |
| 179 if (gpu_data_manager != NULL && !gpu_data_manager->GpuAccessAllowed()) | 197 if (gpu_data_manager != NULL && !gpu_data_manager->GpuAccessAllowed()) |
| 180 return NULL; | 198 return NULL; |
| 181 | 199 |
| 182 // The current policy is to ignore the renderer ID and use a single GPU | 200 // The current policy is to ignore the renderer ID and use a single GPU |
| 183 // process for all renderers. Later this will be extended to allow the | 201 // process for all renderers. Later this will be extended to allow the |
| 184 // use of multiple GPU processes. | 202 // use of multiple GPU processes. |
| 185 if (!g_hosts_by_id.Pointer()->IsEmpty()) { | 203 if (!g_hosts_by_id.Pointer()->IsEmpty()) { |
| 186 IDMap<GpuProcessHost>::iterator it(g_hosts_by_id.Pointer()); | 204 IDMap<GpuProcessHost>::iterator it(g_hosts_by_id.Pointer()); |
| 187 return it.GetCurrentValue(); | 205 GpuProcessHost *host = it.GetCurrentValue(); |
| 206 |
| 207 if (HostIsValid(it.GetCurrentKey(), host)) |
| 208 return host; |
| 188 } | 209 } |
| 189 | 210 |
| 190 if (cause == content::CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH) | 211 if (cause == content::CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH) |
| 191 return NULL; | 212 return NULL; |
| 192 | 213 |
| 193 int host_id; | 214 int host_id; |
| 194 host_id = ++g_last_host_id; | 215 host_id = ++g_last_host_id; |
| 195 | 216 |
| 196 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLaunchCause", | 217 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLaunchCause", |
| 197 cause, | 218 cause, |
| (...skipping 17 matching lines...) Expand all Loading... |
| 215 &SendGpuProcessMessage, renderer_id, cause, message)); | 236 &SendGpuProcessMessage, renderer_id, cause, message)); |
| 216 } | 237 } |
| 217 | 238 |
| 218 // static | 239 // static |
| 219 GpuProcessHost* GpuProcessHost::FromID(int host_id) { | 240 GpuProcessHost* GpuProcessHost::FromID(int host_id) { |
| 220 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 241 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 221 | 242 |
| 222 if (host_id == 0) | 243 if (host_id == 0) |
| 223 return NULL; | 244 return NULL; |
| 224 | 245 |
| 225 return g_hosts_by_id.Pointer()->Lookup(host_id); | 246 GpuProcessHost *host = g_hosts_by_id.Pointer()->Lookup(host_id); |
| 247 if (HostIsValid(host_id, host)) |
| 248 return host; |
| 249 |
| 250 return NULL; |
| 226 } | 251 } |
| 227 | 252 |
| 228 GpuProcessHost::GpuProcessHost(int host_id) | 253 GpuProcessHost::GpuProcessHost(int host_id) |
| 229 : BrowserChildProcessHost(GPU_PROCESS), | 254 : BrowserChildProcessHost(GPU_PROCESS), |
| 230 host_id_(host_id), | 255 host_id_(host_id), |
| 231 gpu_process_(base::kNullProcessHandle), | 256 gpu_process_(base::kNullProcessHandle), |
| 232 in_process_(false) { | 257 in_process_(false), |
| 258 software_rendering_(false) { |
| 233 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) || | 259 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) || |
| 234 CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU)) | 260 CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU)) |
| 235 in_process_ = true; | 261 in_process_ = true; |
| 236 | 262 |
| 237 // If the 'single GPU process' policy ever changes, we still want to maintain | 263 // If the 'single GPU process' policy ever changes, we still want to maintain |
| 238 // it for 'gpu thread' mode and only create one instance of host and thread. | 264 // it for 'gpu thread' mode and only create one instance of host and thread. |
| 239 DCHECK(!in_process_ || g_hosts_by_id.Pointer()->IsEmpty()); | 265 DCHECK(!in_process_ || g_hosts_by_id.Pointer()->IsEmpty()); |
| 240 | 266 |
| 241 g_hosts_by_id.Pointer()->AddWithID(this, host_id_); | 267 g_hosts_by_id.Pointer()->AddWithID(this, host_id_); |
| 242 | 268 |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 509 | 535 |
| 510 void GpuProcessHost::OnProcessCrashed(int exit_code) { | 536 void GpuProcessHost::OnProcessCrashed(int exit_code) { |
| 511 SendOutstandingReplies(); | 537 SendOutstandingReplies(); |
| 512 if (++g_gpu_crash_count >= kGpuMaxCrashCount) { | 538 if (++g_gpu_crash_count >= kGpuMaxCrashCount) { |
| 513 // The gpu process is too unstable to use. Disable it for current session. | 539 // The gpu process is too unstable to use. Disable it for current session. |
| 514 gpu_enabled_ = false; | 540 gpu_enabled_ = false; |
| 515 } | 541 } |
| 516 BrowserChildProcessHost::OnProcessCrashed(exit_code); | 542 BrowserChildProcessHost::OnProcessCrashed(exit_code); |
| 517 } | 543 } |
| 518 | 544 |
| 545 bool GpuProcessHost::SoftwareRendering() { |
| 546 return software_rendering_; |
| 547 } |
| 548 |
| 519 bool GpuProcessHost::LaunchGpuProcess() { | 549 bool GpuProcessHost::LaunchGpuProcess() { |
| 520 if (!gpu_enabled_ || g_gpu_crash_count >= kGpuMaxCrashCount) { | 550 if (!gpu_enabled_ || g_gpu_crash_count >= kGpuMaxCrashCount) { |
| 521 SendOutstandingReplies(); | 551 SendOutstandingReplies(); |
| 522 gpu_enabled_ = false; | 552 gpu_enabled_ = false; |
| 523 return false; | 553 return false; |
| 524 } | 554 } |
| 525 | 555 |
| 526 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); | 556 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); |
| 527 | 557 |
| 528 CommandLine::StringType gpu_launcher = | 558 CommandLine::StringType gpu_launcher = |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 566 arraysize(kSwitchNames)); | 596 arraysize(kSwitchNames)); |
| 567 | 597 |
| 568 // If --ignore-gpu-blacklist is passed in, don't send in crash reports | 598 // If --ignore-gpu-blacklist is passed in, don't send in crash reports |
| 569 // because GPU is expected to be unreliable. | 599 // because GPU is expected to be unreliable. |
| 570 if (browser_command_line.HasSwitch(switches::kIgnoreGpuBlacklist) && | 600 if (browser_command_line.HasSwitch(switches::kIgnoreGpuBlacklist) && |
| 571 !cmd_line->HasSwitch(switches::kDisableBreakpad)) | 601 !cmd_line->HasSwitch(switches::kDisableBreakpad)) |
| 572 cmd_line->AppendSwitch(switches::kDisableBreakpad); | 602 cmd_line->AppendSwitch(switches::kDisableBreakpad); |
| 573 | 603 |
| 574 GpuDataManager::GetInstance()->AppendGpuCommandLine(cmd_line); | 604 GpuDataManager::GetInstance()->AppendGpuCommandLine(cmd_line); |
| 575 | 605 |
| 606 if (cmd_line->HasSwitch(switches::kUseGL)) |
| 607 software_rendering_ = |
| 608 (cmd_line->GetSwitchValueASCII(switches::kUseGL) == "swiftshader"); |
| 609 |
| 576 // If specified, prepend a launcher program to the command line. | 610 // If specified, prepend a launcher program to the command line. |
| 577 if (!gpu_launcher.empty()) | 611 if (!gpu_launcher.empty()) |
| 578 cmd_line->PrependWrapper(gpu_launcher); | 612 cmd_line->PrependWrapper(gpu_launcher); |
| 579 | 613 |
| 580 Launch( | 614 Launch( |
| 581 #if defined(OS_WIN) | 615 #if defined(OS_WIN) |
| 582 FilePath(), | 616 FilePath(), |
| 583 #elif defined(OS_POSIX) | 617 #elif defined(OS_POSIX) |
| 584 false, // Never use the zygote (GPU plugin can't be sandboxed). | 618 false, // Never use the zygote (GPU plugin can't be sandboxed). |
| 585 base::environment_vector(), | 619 base::environment_vector(), |
| (...skipping 25 matching lines...) Expand all Loading... |
| 611 scoped_ptr<EstablishChannelCallback> wrapped_callback(callback); | 645 scoped_ptr<EstablishChannelCallback> wrapped_callback(callback); |
| 612 wrapped_callback->Run(channel_handle, renderer_process_for_gpu, gpu_info); | 646 wrapped_callback->Run(channel_handle, renderer_process_for_gpu, gpu_info); |
| 613 } | 647 } |
| 614 | 648 |
| 615 void GpuProcessHost::CreateCommandBufferError( | 649 void GpuProcessHost::CreateCommandBufferError( |
| 616 CreateCommandBufferCallback* callback, int32 route_id) { | 650 CreateCommandBufferCallback* callback, int32 route_id) { |
| 617 scoped_ptr<GpuProcessHost::CreateCommandBufferCallback> | 651 scoped_ptr<GpuProcessHost::CreateCommandBufferCallback> |
| 618 wrapped_callback(callback); | 652 wrapped_callback(callback); |
| 619 callback->Run(route_id); | 653 callback->Run(route_id); |
| 620 } | 654 } |
| OLD | NEW |