Chromium Code Reviews| Index: content/browser/gpu/gpu_process_host.cc |
| diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc |
| index a54fe75722d8b2709528479960524802449c0094..311fe1ef292e48553fdb0c54c5b4eee8cfd29774 100644 |
| --- a/content/browser/gpu/gpu_process_host.cc |
| +++ b/content/browser/gpu/gpu_process_host.cc |
| @@ -10,6 +10,7 @@ |
| #include "base/metrics/histogram.h" |
| #include "base/process_util.h" |
| #include "base/string_piece.h" |
| +#include "base/threading/thread.h" |
| #include "chrome/browser/tab_contents/render_view_host_delegate_helper.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/common/render_messages.h" |
| @@ -19,6 +20,8 @@ |
| #include "content/browser/renderer_host/render_widget_host.h" |
| #include "content/browser/renderer_host/render_widget_host_view.h" |
| #include "content/common/gpu/gpu_messages.h" |
| +#include "content/gpu/gpu_child_thread.h" |
| +#include "content/gpu/gpu_process.h" |
| #include "ipc/ipc_channel_handle.h" |
| #include "ipc/ipc_switches.h" |
| #include "media/base/media_switches.h" |
| @@ -115,6 +118,42 @@ GpuProcessHost::SurfaceRef::~SurfaceRef() { |
| } |
| #endif // defined(OS_LINUX) |
| +// This class creates a GPU thread (instead of a GPU process), when running |
| +// with --in-process-gpu or --single-process. |
| +class GpuThreadWrapper : public base::Thread { |
| + public: |
| + explicit GpuThreadWrapper(const std::string& channel_id) |
| + : base::Thread("Chrome_InProcGpuThread"), |
| + channel_id_(channel_id), |
| + gpu_process_(NULL) { |
| + } |
| + |
| + ~GpuThreadWrapper() { |
| + Stop(); |
| + } |
| + |
| + protected: |
| + virtual void Init() { |
| + // TODO: Currently, ChildProcess supports only a single static instance, |
| + // which is a problem in --single-process mode, where both gpu and renderer |
| + // should be able to create separate instances. |
| + DCHECK(!GpuProcess::current()); |
|
jam
2011/05/26 01:15:24
what happens if someone uses --single-process mode
Daniel Sievers (Google)
2011/05/26 01:35:09
Before this change, it would just not work (time o
|
| + gpu_process_ = new GpuProcess(); |
| + gpu_process_->set_main_thread(new GpuChildThread(channel_id_)); |
| + } |
| + |
| + virtual void CleanUp() { |
| + delete gpu_process_; |
| + } |
| + |
| + private: |
| + std::string channel_id_; |
| + // Deleted in CleanUp() on the gpu thread, so don't use smart pointers. |
| + GpuProcess* gpu_process_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(GpuThreadWrapper); |
| +}; |
| + |
| // static |
| GpuProcessHost* GpuProcessHost::GetForRenderer( |
| int renderer_id, content::CauseForGpuLaunch cause) { |
| @@ -136,36 +175,22 @@ GpuProcessHost* GpuProcessHost::GetForRenderer( |
| if (cause == content::CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH) |
| return NULL; |
| + bool in_process = |
|
jam
2011/05/26 01:15:24
can you move the in_process bits to inside of GpuP
|
| + CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) || |
| + CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU); |
| + |
| + // If the 'single GPU process' policy ever changes, we still want to maintain |
| + // it for 'gpu thread' mode and only create one instance of host and thread. |
| + DCHECK(!in_process || g_hosts_by_id.IsEmpty()); |
| + |
| int host_id; |
| - /* TODO(apatrick): this is currently broken because this function is called on |
| - the IO thread from GpuMessageFilter, and we don't have an IO thread object |
| - when running the GPU code in the browser at the moment. |
| - if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) || |
| - CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU)) { |
| - if (!g_browser_process->gpu_thread()) |
| - return NULL; |
| - |
| - // Initialize GL on the GPU thread. |
| - // TODO(apatrick): Handle failure to initialize (asynchronously). |
| - if (!BrowserThread::PostTask( |
| - BrowserThread::GPU, |
| - FROM_HERE, |
| - NewRunnableFunction(&gfx::GLContext::InitializeOneOff))) { |
| - return NULL; |
| - } |
| - |
| - host_id = 0; |
| - } else { |
| - host_id = ++g_last_host_id; |
| - } |
| - */ |
| host_id = ++g_last_host_id; |
| UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLaunchCause", |
| cause, |
| content::CAUSE_FOR_GPU_LAUNCH_MAX_ENUM); |
| - GpuProcessHost* host = new GpuProcessHost(host_id); |
| + GpuProcessHost* host = new GpuProcessHost(host_id, in_process); |
| if (host->Init()) |
| return host; |
| @@ -193,10 +218,11 @@ GpuProcessHost* GpuProcessHost::FromID(int host_id) { |
| return g_hosts_by_id.Lookup(host_id); |
| } |
| -GpuProcessHost::GpuProcessHost(int host_id) |
| +GpuProcessHost::GpuProcessHost(int host_id, bool in_process) |
| : BrowserChildProcessHost(GPU_PROCESS), |
| host_id_(host_id), |
| - gpu_process_(base::kNullProcessHandle) { |
| + gpu_process_(base::kNullProcessHandle), |
| + in_process_(in_process) { |
| g_hosts_by_id.AddWithID(this, host_id_); |
| if (host_id == 0) |
| gpu_process_ = base::GetCurrentProcessHandle(); |
| @@ -237,7 +263,27 @@ bool GpuProcessHost::Init() { |
| if (!CreateChannel()) |
| return false; |
| - if (!LaunchGpuProcess()) |
| + if (in_process_) { |
| + CommandLine::ForCurrentProcess()->AppendSwitch( |
| + switches::kDisableGpuWatchdog); |
| + |
| + in_process_gpu_thread_.reset(new GpuThreadWrapper(channel_id())); |
| + |
| + base::Thread::Options options; |
| +#if defined(OS_WIN) |
| + // On Windows the GPU thread needs to pump the compositor child window's |
| + // message loop. TODO(apatrick): make this an IO thread if / when we get rid |
| + // of this child window. Unfortunately it might always be necessary for |
| + // Windows XP because we cannot share the backing store textures between |
| + // processes. |
| + options.message_loop_type = MessageLoop::TYPE_UI; |
| +#else |
| + options.message_loop_type = MessageLoop::TYPE_IO; |
| +#endif |
| + in_process_gpu_thread_->StartWithOptions(options); |
| + |
| + OnProcessLaunched(); // Fake a callback that the process is ready. |
| + } else if (!LaunchGpuProcess()) |
| return false; |
| return Send(new GpuMsg_Initialize()); |
| @@ -427,16 +473,20 @@ void GpuProcessHost::OnProcessLaunched() { |
| // Send the GPU process handle to the UI thread before it has to |
| // respond to any requests to establish a GPU channel. The response |
| // to such requests require that the GPU process handle be known. |
| + |
| + base::ProcessHandle child_handle = in_process_ ? |
| + base::GetCurrentProcessHandle() : handle(); |
| + |
| #if defined(OS_WIN) |
| DuplicateHandle(base::GetCurrentProcessHandle(), |
| - handle(), |
| + child_handle, |
| base::GetCurrentProcessHandle(), |
| &gpu_process_, |
| PROCESS_DUP_HANDLE, |
| FALSE, |
| 0); |
| #else |
| - gpu_process_ = handle(); |
| + gpu_process_ = child_handle; |
| #endif |
| } |