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..5f25e93ab2f324f5972723805b2a3bc170e19a3b 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,51 @@ 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 GpuMainThread : public base::Thread { |
+ public: |
+ explicit GpuMainThread(const std::string& channel_id) |
+ : base::Thread("Chrome_InProcGpuThread"), |
+ channel_id_(channel_id), |
+ gpu_process_(NULL), |
+ child_thread_(NULL) { |
+ } |
+ |
+ ~GpuMainThread() { |
+ 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. |
+ if (GpuProcess::current()) { |
+ child_thread_ = new GpuChildThread(channel_id_); |
+ } else { |
+ gpu_process_ = new GpuProcess(); |
+ // The process object takes ownership of the thread object, so do not |
+ // save and delete the pointer. |
+ gpu_process_->set_main_thread(new GpuChildThread(channel_id_)); |
+ } |
+ } |
+ |
+ virtual void CleanUp() { |
+ delete gpu_process_; |
+ if (child_thread_) |
+ delete child_thread_; |
+ } |
+ |
+ private: |
+ std::string channel_id_; |
+ // Deleted in CleanUp() on the gpu thread, so don't use smart pointers. |
+ GpuProcess* gpu_process_; |
+ GpuChildThread* child_thread_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(GpuMainThread); |
+}; |
+ |
// static |
GpuProcessHost* GpuProcessHost::GetForRenderer( |
int renderer_id, content::CauseForGpuLaunch cause) { |
@@ -137,28 +185,6 @@ GpuProcessHost* GpuProcessHost::GetForRenderer( |
return NULL; |
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", |
@@ -196,10 +222,17 @@ GpuProcessHost* GpuProcessHost::FromID(int host_id) { |
GpuProcessHost::GpuProcessHost(int host_id) |
: BrowserChildProcessHost(GPU_PROCESS), |
host_id_(host_id), |
- gpu_process_(base::kNullProcessHandle) { |
+ gpu_process_(base::kNullProcessHandle), |
+ in_process_(false) { |
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) || |
+ CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU)) |
+ in_process_ = true; |
+ |
+ // 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()); |
+ |
g_hosts_by_id.AddWithID(this, host_id_); |
- if (host_id == 0) |
- gpu_process_ = base::GetCurrentProcessHandle(); |
// Post a task to create the corresponding GpuProcessHostUIShim. The |
// GpuProcessHostUIShim will be destroyed if either the browser exits, |
@@ -237,7 +270,27 @@ bool GpuProcessHost::Init() { |
if (!CreateChannel()) |
return false; |
- if (!LaunchGpuProcess()) |
+ if (in_process_) { |
+ CommandLine::ForCurrentProcess()->AppendSwitch( |
+ switches::kDisableGpuWatchdog); |
+ |
+ in_process_gpu_thread_.reset(new GpuMainThread(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 +480,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 |
} |