| 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 |