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/base_switches.h" | 7 #include "base/base_switches.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/bind_helpers.h" | 9 #include "base/bind_helpers.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 | 72 |
73 #if defined(TOOLKIT_USES_GTK) | 73 #if defined(TOOLKIT_USES_GTK) |
74 | 74 |
75 void ReleasePermanentXIDDispatcher(gfx::PluginWindowHandle surface) { | 75 void ReleasePermanentXIDDispatcher(gfx::PluginWindowHandle surface) { |
76 GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance(); | 76 GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance(); |
77 manager->ReleasePermanentXID(surface); | 77 manager->ReleasePermanentXID(surface); |
78 } | 78 } |
79 | 79 |
80 #endif | 80 #endif |
81 | 81 |
82 void SendGpuProcessMessage(int client_id, | 82 void SendGpuProcessMessage(GpuProcessHost::GpuProcessKind kind, |
83 content::CauseForGpuLaunch cause, | 83 content::CauseForGpuLaunch cause, |
84 IPC::Message* message) { | 84 IPC::Message* message) { |
85 GpuProcessHost* host = GpuProcessHost::GetForClient(client_id, cause); | 85 GpuProcessHost* host = GpuProcessHost::Get(kind, cause); |
86 if (host) { | 86 if (host) { |
87 host->Send(message); | 87 host->Send(message); |
88 } else { | 88 } else { |
89 delete message; | 89 delete message; |
90 } | 90 } |
91 } | 91 } |
92 | 92 |
93 void AcceleratedSurfaceBuffersSwappedCompleted(int host_id, | 93 void AcceleratedSurfaceBuffersSwappedCompleted(int host_id, |
94 int route_id, | 94 int route_id, |
95 bool alive) { | 95 bool alive) { |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 host->software_rendering() || | 201 host->software_rendering() || |
202 !GpuDataManagerImpl::GetInstance()->ShouldUseSoftwareRendering()) { | 202 !GpuDataManagerImpl::GetInstance()->ShouldUseSoftwareRendering()) { |
203 return true; | 203 return true; |
204 } | 204 } |
205 | 205 |
206 host->ForceShutdown(); | 206 host->ForceShutdown(); |
207 return false; | 207 return false; |
208 } | 208 } |
209 | 209 |
210 // static | 210 // static |
211 GpuProcessHost* GpuProcessHost::GetForClient( | 211 GpuProcessHost* GpuProcessHost::Get(GpuProcessKind kind, |
212 int client_id, content::CauseForGpuLaunch cause) { | 212 content::CauseForGpuLaunch cause) { |
213 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 213 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
214 | 214 |
215 // Don't grant further access to GPU if it is not allowed. | 215 // Don't grant further access to GPU if it is not allowed. |
216 GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance(); | 216 GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance(); |
217 if (gpu_data_manager != NULL && !gpu_data_manager->GpuAccessAllowed()) | 217 if (gpu_data_manager != NULL && !gpu_data_manager->GpuAccessAllowed()) |
218 return NULL; | 218 return NULL; |
219 | 219 |
220 // The current policy is to ignore the renderer ID and use a single GPU | 220 // TODO(apatrick): This is a mess. There are only two GpuProcessHosts that |
221 // process (the first valid host in the host-id map) for all renderers. Later | 221 // can legitimately be returned by this function: the sandboxed one or the |
222 // this will be extended to allow the use of multiple GPU processes. | 222 // unsandboxed one. There should be no need for a map indexed by host ID. |
| 223 // Historical note: there was once a command line switch to launch one GPU |
| 224 // process per renderer process and this is its legacy. |
223 for (IDMap<GpuProcessHost>::iterator it(g_hosts_by_id.Pointer()); | 225 for (IDMap<GpuProcessHost>::iterator it(g_hosts_by_id.Pointer()); |
224 !it.IsAtEnd(); it.Advance()) { | 226 !it.IsAtEnd(); it.Advance()) { |
225 GpuProcessHost* host = it.GetCurrentValue(); | 227 GpuProcessHost* host = it.GetCurrentValue(); |
226 | 228 |
227 if (host->sandboxed() != (client_id != 0)) | 229 if (host->kind() != kind) |
228 continue; | 230 continue; |
229 | 231 |
230 if (HostIsValid(host)) | 232 if (HostIsValid(host)) |
231 return host; | 233 return host; |
232 } | 234 } |
233 | 235 |
234 if (cause == content::CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH) | 236 if (cause == content::CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH) |
235 return NULL; | 237 return NULL; |
236 | 238 |
237 int host_id; | 239 int host_id; |
238 host_id = ++g_last_host_id; | 240 host_id = ++g_last_host_id; |
239 | 241 |
240 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLaunchCause", | 242 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLaunchCause", |
241 cause, | 243 cause, |
242 content::CAUSE_FOR_GPU_LAUNCH_MAX_ENUM); | 244 content::CAUSE_FOR_GPU_LAUNCH_MAX_ENUM); |
243 | 245 |
244 GpuProcessHost* host = new GpuProcessHost(host_id, client_id != 0); | 246 GpuProcessHost* host = new GpuProcessHost(host_id, kind); |
245 if (host->Init()) | 247 if (host->Init()) |
246 return host; | 248 return host; |
247 | 249 |
248 delete host; | 250 delete host; |
249 return NULL; | 251 return NULL; |
250 } | 252 } |
251 | 253 |
252 // static | 254 // static |
253 void GpuProcessHost::SendOnIO(int client_id, | 255 void GpuProcessHost::SendOnIO(GpuProcessKind kind, |
254 content::CauseForGpuLaunch cause, | 256 content::CauseForGpuLaunch cause, |
255 IPC::Message* message) { | 257 IPC::Message* message) { |
256 BrowserThread::PostTask( | 258 BrowserThread::PostTask( |
257 BrowserThread::IO, FROM_HERE, | 259 BrowserThread::IO, FROM_HERE, |
258 base::Bind( | 260 base::Bind( |
259 &SendGpuProcessMessage, client_id, cause, message)); | 261 &SendGpuProcessMessage, kind, cause, message)); |
260 } | 262 } |
261 | 263 |
262 // static | 264 // static |
263 GpuProcessHost* GpuProcessHost::FromID(int host_id) { | 265 GpuProcessHost* GpuProcessHost::FromID(int host_id) { |
264 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 266 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
265 | 267 |
266 if (host_id == 0) | 268 if (host_id == 0) |
267 return NULL; | 269 return NULL; |
268 | 270 |
269 GpuProcessHost* host = g_hosts_by_id.Pointer()->Lookup(host_id); | 271 GpuProcessHost* host = g_hosts_by_id.Pointer()->Lookup(host_id); |
270 if (HostIsValid(host)) | 272 if (HostIsValid(host)) |
271 return host; | 273 return host; |
272 | 274 |
273 return NULL; | 275 return NULL; |
274 } | 276 } |
275 | 277 |
276 GpuProcessHost::GpuProcessHost(int host_id, bool sandboxed) | 278 GpuProcessHost::GpuProcessHost(int host_id, GpuProcessKind kind) |
277 : host_id_(host_id), | 279 : host_id_(host_id), |
278 gpu_process_(base::kNullProcessHandle), | 280 gpu_process_(base::kNullProcessHandle), |
279 in_process_(false), | 281 in_process_(false), |
280 software_rendering_(false), | 282 software_rendering_(false), |
281 sandboxed_(sandboxed), | 283 kind_(kind), |
282 process_launched_(false) { | 284 process_launched_(false) { |
283 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) || | 285 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) || |
284 CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU)) | 286 CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU)) |
285 in_process_ = true; | 287 in_process_ = true; |
286 | 288 |
287 // If the 'single GPU process' policy ever changes, we still want to maintain | 289 // If the 'single GPU process' policy ever changes, we still want to maintain |
288 // it for 'gpu thread' mode and only create one instance of host and thread. | 290 // it for 'gpu thread' mode and only create one instance of host and thread. |
289 DCHECK(!in_process_ || g_hosts_by_id.Pointer()->IsEmpty()); | 291 DCHECK(!in_process_ || g_hosts_by_id.Pointer()->IsEmpty()); |
290 | 292 |
291 g_hosts_by_id.Pointer()->AddWithID(this, host_id_); | 293 g_hosts_by_id.Pointer()->AddWithID(this, host_id_); |
(...skipping 12 matching lines...) Expand all Loading... |
304 new BrowserChildProcessHostImpl(content::PROCESS_TYPE_GPU, this)); | 306 new BrowserChildProcessHostImpl(content::PROCESS_TYPE_GPU, this)); |
305 } | 307 } |
306 | 308 |
307 GpuProcessHost::~GpuProcessHost() { | 309 GpuProcessHost::~GpuProcessHost() { |
308 DCHECK(CalledOnValidThread()); | 310 DCHECK(CalledOnValidThread()); |
309 | 311 |
310 SendOutstandingReplies(); | 312 SendOutstandingReplies(); |
311 // Ending only acts as a failure if the GPU process was actually started and | 313 // Ending only acts as a failure if the GPU process was actually started and |
312 // was intended for actual rendering (and not just checking caps or other | 314 // was intended for actual rendering (and not just checking caps or other |
313 // options). | 315 // options). |
314 if (process_launched_ && sandboxed_) { | 316 if (process_launched_ && kind_ == GPU_PROCESS_KIND_SANDBOXED) { |
315 if (software_rendering_) { | 317 if (software_rendering_) { |
316 if (++g_gpu_software_crash_count >= kGpuMaxCrashCount) { | 318 if (++g_gpu_software_crash_count >= kGpuMaxCrashCount) { |
317 // The software renderer is too unstable to use. Disable it for current | 319 // The software renderer is too unstable to use. Disable it for current |
318 // session. | 320 // session. |
319 gpu_enabled_ = false; | 321 gpu_enabled_ = false; |
320 } | 322 } |
321 } else { | 323 } else { |
322 if (++g_gpu_crash_count >= kGpuMaxCrashCount) { | 324 if (++g_gpu_crash_count >= kGpuMaxCrashCount) { |
323 // The gpu process is too unstable to use. Disable it for current | 325 // The gpu process is too unstable to use. Disable it for current |
324 // session. | 326 // session. |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 void GpuProcessHost::OnAcceleratedSurfaceBuffersSwapped( | 551 void GpuProcessHost::OnAcceleratedSurfaceBuffersSwapped( |
550 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params) { | 552 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params) { |
551 TRACE_EVENT0("renderer", | 553 TRACE_EVENT0("renderer", |
552 "GpuProcessHost::OnAcceleratedSurfaceBuffersSwapped"); | 554 "GpuProcessHost::OnAcceleratedSurfaceBuffersSwapped"); |
553 | 555 |
554 GpuSurfaceTracker::Get()->AsyncPresentAndAcknowledge( | 556 GpuSurfaceTracker::Get()->AsyncPresentAndAcknowledge( |
555 params.surface_id, | 557 params.surface_id, |
556 params.size, | 558 params.size, |
557 params.surface_handle, | 559 params.surface_handle, |
558 base::Bind(&AcceleratedSurfaceBuffersSwappedCompleted, | 560 base::Bind(&AcceleratedSurfaceBuffersSwappedCompleted, |
559 host_id_, | 561 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, |
560 params.route_id)); | 562 params.route_id)); |
561 } | 563 } |
562 | 564 |
563 void GpuProcessHost::OnAcceleratedSurfacePostSubBuffer( | 565 void GpuProcessHost::OnAcceleratedSurfacePostSubBuffer( |
564 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params) { | 566 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params) { |
565 TRACE_EVENT0("renderer", | 567 TRACE_EVENT0("renderer", |
566 "GpuProcessHost::OnAcceleratedSurfacePostSubBuffer"); | 568 "GpuProcessHost::OnAcceleratedSurfacePostSubBuffer"); |
567 | 569 |
568 NOTIMPLEMENTED(); | 570 NOTIMPLEMENTED(); |
569 } | 571 } |
(...skipping 29 matching lines...) Expand all Loading... |
599 } | 601 } |
600 | 602 |
601 void GpuProcessHost::OnProcessCrashed(int exit_code) { | 603 void GpuProcessHost::OnProcessCrashed(int exit_code) { |
602 SendOutstandingReplies(); | 604 SendOutstandingReplies(); |
603 } | 605 } |
604 | 606 |
605 bool GpuProcessHost::software_rendering() { | 607 bool GpuProcessHost::software_rendering() { |
606 return software_rendering_; | 608 return software_rendering_; |
607 } | 609 } |
608 | 610 |
609 bool GpuProcessHost::sandboxed() { | 611 GpuProcessHost::GpuProcessKind GpuProcessHost::kind() { |
610 return sandboxed_; | 612 return kind_; |
611 } | 613 } |
612 | 614 |
613 void GpuProcessHost::ForceShutdown() { | 615 void GpuProcessHost::ForceShutdown() { |
614 g_hosts_by_id.Pointer()->Remove(host_id_); | 616 g_hosts_by_id.Pointer()->Remove(host_id_); |
615 process_->ForceShutdown(); | 617 process_->ForceShutdown(); |
616 } | 618 } |
617 | 619 |
618 bool GpuProcessHost::LaunchGpuProcess(const std::string& channel_id) { | 620 bool GpuProcessHost::LaunchGpuProcess(const std::string& channel_id) { |
619 if (!(gpu_enabled_ && | 621 if (!(gpu_enabled_ && |
620 GpuDataManagerImpl::GetInstance()->ShouldUseSoftwareRendering()) && | 622 GpuDataManagerImpl::GetInstance()->ShouldUseSoftwareRendering()) && |
(...skipping 15 matching lines...) Expand all Loading... |
636 #endif | 638 #endif |
637 | 639 |
638 FilePath exe_path = ChildProcessHost::GetChildPath(child_flags); | 640 FilePath exe_path = ChildProcessHost::GetChildPath(child_flags); |
639 if (exe_path.empty()) | 641 if (exe_path.empty()) |
640 return false; | 642 return false; |
641 | 643 |
642 CommandLine* cmd_line = new CommandLine(exe_path); | 644 CommandLine* cmd_line = new CommandLine(exe_path); |
643 cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kGpuProcess); | 645 cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kGpuProcess); |
644 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id); | 646 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id); |
645 | 647 |
646 if (!sandboxed_) | 648 if (kind_ == GPU_PROCESS_KIND_UNSANDBOXED) |
647 cmd_line->AppendSwitch(switches::kDisableGpuSandbox); | 649 cmd_line->AppendSwitch(switches::kDisableGpuSandbox); |
648 | 650 |
649 // Propagate relevant command line switches. | 651 // Propagate relevant command line switches. |
650 static const char* const kSwitchNames[] = { | 652 static const char* const kSwitchNames[] = { |
651 switches::kDisableBreakpad, | 653 switches::kDisableBreakpad, |
652 switches::kDisableGLMultisampling, | 654 switches::kDisableGLMultisampling, |
653 switches::kDisableGpuDriverBugWorkarounds, | 655 switches::kDisableGpuDriverBugWorkarounds, |
654 switches::kDisableGpuSandbox, | 656 switches::kDisableGpuSandbox, |
655 switches::kReduceGpuSandbox, | 657 switches::kReduceGpuSandbox, |
656 switches::kDisableGpuVsync, | 658 switches::kDisableGpuVsync, |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
719 const IPC::ChannelHandle& channel_handle, | 721 const IPC::ChannelHandle& channel_handle, |
720 base::ProcessHandle renderer_process_for_gpu, | 722 base::ProcessHandle renderer_process_for_gpu, |
721 const content::GPUInfo& gpu_info) { | 723 const content::GPUInfo& gpu_info) { |
722 callback.Run(channel_handle, renderer_process_for_gpu, gpu_info); | 724 callback.Run(channel_handle, renderer_process_for_gpu, gpu_info); |
723 } | 725 } |
724 | 726 |
725 void GpuProcessHost::CreateCommandBufferError( | 727 void GpuProcessHost::CreateCommandBufferError( |
726 const CreateCommandBufferCallback& callback, int32 route_id) { | 728 const CreateCommandBufferCallback& callback, int32 route_id) { |
727 callback.Run(route_id); | 729 callback.Run(route_id); |
728 } | 730 } |
OLD | NEW |