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->software_rendering() || |
| 181 !GpuDataManager::GetInstance()->software_rendering()) { |
| 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::software_rendering() { |
| 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 |