Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(128)

Side by Side Diff: content/browser/gpu/gpu_process_host.cc

Issue 7054005: Fix gpu acceleration with --in-process-gpu (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: remove obsolete files Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/command_line.h" 7 #include "base/command_line.h"
8 #include "base/debug/trace_event.h" 8 #include "base/debug/trace_event.h"
9 #include "base/memory/ref_counted.h" 9 #include "base/memory/ref_counted.h"
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
11 #include "base/process_util.h" 11 #include "base/process_util.h"
12 #include "base/string_piece.h" 12 #include "base/string_piece.h"
13 #include "base/threading/thread.h"
13 #include "chrome/browser/tab_contents/render_view_host_delegate_helper.h" 14 #include "chrome/browser/tab_contents/render_view_host_delegate_helper.h"
14 #include "chrome/common/chrome_switches.h" 15 #include "chrome/common/chrome_switches.h"
15 #include "chrome/common/render_messages.h" 16 #include "chrome/common/render_messages.h"
16 #include "content/browser/browser_thread.h" 17 #include "content/browser/browser_thread.h"
17 #include "content/browser/gpu/gpu_data_manager.h" 18 #include "content/browser/gpu/gpu_data_manager.h"
18 #include "content/browser/gpu/gpu_process_host_ui_shim.h" 19 #include "content/browser/gpu/gpu_process_host_ui_shim.h"
19 #include "content/browser/renderer_host/render_widget_host.h" 20 #include "content/browser/renderer_host/render_widget_host.h"
20 #include "content/browser/renderer_host/render_widget_host_view.h" 21 #include "content/browser/renderer_host/render_widget_host_view.h"
21 #include "content/common/gpu/gpu_messages.h" 22 #include "content/common/gpu/gpu_messages.h"
23 #include "content/gpu/gpu_child_thread.h"
24 #include "content/gpu/gpu_process.h"
22 #include "ipc/ipc_channel_handle.h" 25 #include "ipc/ipc_channel_handle.h"
23 #include "ipc/ipc_switches.h" 26 #include "ipc/ipc_switches.h"
24 #include "media/base/media_switches.h" 27 #include "media/base/media_switches.h"
25 #include "ui/gfx/gl/gl_context.h" 28 #include "ui/gfx/gl/gl_context.h"
26 #include "ui/gfx/gl/gl_switches.h" 29 #include "ui/gfx/gl/gl_switches.h"
27 30
28 #if defined(OS_LINUX) 31 #if defined(OS_LINUX)
29 #include "ui/gfx/gtk_native_view_id_manager.h" 32 #include "ui/gfx/gtk_native_view_id_manager.h"
30 #endif // defined(OS_LINUX) 33 #endif // defined(OS_LINUX)
31 34
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 } 111 }
109 } 112 }
110 113
111 GpuProcessHost::SurfaceRef::~SurfaceRef() { 114 GpuProcessHost::SurfaceRef::~SurfaceRef() {
112 BrowserThread::PostTask(BrowserThread::UI, 115 BrowserThread::PostTask(BrowserThread::UI,
113 FROM_HERE, 116 FROM_HERE,
114 new ReleasePermanentXIDDispatcher(surface_)); 117 new ReleasePermanentXIDDispatcher(surface_));
115 } 118 }
116 #endif // defined(OS_LINUX) 119 #endif // defined(OS_LINUX)
117 120
121 // This class creates a GPU thread (instead of a GPU process), when running
122 // with --in-process-gpu or --single-process.
123 class GpuThreadWrapper : public base::Thread {
124 public:
125 explicit GpuThreadWrapper(const std::string& channel_id)
126 : base::Thread("Chrome_InProcGpuThread"),
127 channel_id_(channel_id),
128 gpu_process_(NULL) {
129 }
130
131 ~GpuThreadWrapper() {
132 Stop();
133 }
134
135 protected:
136 virtual void Init() {
137 // TODO: Currently, ChildProcess supports only a single static instance,
138 // which is a problem in --single-process mode, where both gpu and renderer
139 // should be able to create separate instances.
140 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
141 gpu_process_ = new GpuProcess();
142 gpu_process_->set_main_thread(new GpuChildThread(channel_id_));
143 }
144
145 virtual void CleanUp() {
146 delete gpu_process_;
147 }
148
149 private:
150 std::string channel_id_;
151 // Deleted in CleanUp() on the gpu thread, so don't use smart pointers.
152 GpuProcess* gpu_process_;
153
154 DISALLOW_COPY_AND_ASSIGN(GpuThreadWrapper);
155 };
156
118 // static 157 // static
119 GpuProcessHost* GpuProcessHost::GetForRenderer( 158 GpuProcessHost* GpuProcessHost::GetForRenderer(
120 int renderer_id, content::CauseForGpuLaunch cause) { 159 int renderer_id, content::CauseForGpuLaunch cause) {
121 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 160 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
122 161
123 // Don't grant further access to GPU if it is not allowed. 162 // Don't grant further access to GPU if it is not allowed.
124 GpuDataManager* gpu_data_manager = GpuDataManager::GetInstance(); 163 GpuDataManager* gpu_data_manager = GpuDataManager::GetInstance();
125 if (gpu_data_manager != NULL && !gpu_data_manager->GpuAccessAllowed()) 164 if (gpu_data_manager != NULL && !gpu_data_manager->GpuAccessAllowed())
126 return NULL; 165 return NULL;
127 166
128 // The current policy is to ignore the renderer ID and use a single GPU 167 // The current policy is to ignore the renderer ID and use a single GPU
129 // process for all renderers. Later this will be extended to allow the 168 // process for all renderers. Later this will be extended to allow the
130 // use of multiple GPU processes. 169 // use of multiple GPU processes.
131 if (!g_hosts_by_id.IsEmpty()) { 170 if (!g_hosts_by_id.IsEmpty()) {
132 IDMap<GpuProcessHost>::iterator it(&g_hosts_by_id); 171 IDMap<GpuProcessHost>::iterator it(&g_hosts_by_id);
133 return it.GetCurrentValue(); 172 return it.GetCurrentValue();
134 } 173 }
135 174
136 if (cause == content::CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH) 175 if (cause == content::CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH)
137 return NULL; 176 return NULL;
138 177
178 bool in_process =
jam 2011/05/26 01:15:24 can you move the in_process bits to inside of GpuP
179 CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) ||
180 CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU);
181
182 // If the 'single GPU process' policy ever changes, we still want to maintain
183 // it for 'gpu thread' mode and only create one instance of host and thread.
184 DCHECK(!in_process || g_hosts_by_id.IsEmpty());
185
139 int host_id; 186 int host_id;
140 /* TODO(apatrick): this is currently broken because this function is called on
141 the IO thread from GpuMessageFilter, and we don't have an IO thread object
142 when running the GPU code in the browser at the moment.
143 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) ||
144 CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU)) {
145 if (!g_browser_process->gpu_thread())
146 return NULL;
147
148 // Initialize GL on the GPU thread.
149 // TODO(apatrick): Handle failure to initialize (asynchronously).
150 if (!BrowserThread::PostTask(
151 BrowserThread::GPU,
152 FROM_HERE,
153 NewRunnableFunction(&gfx::GLContext::InitializeOneOff))) {
154 return NULL;
155 }
156
157 host_id = 0;
158 } else {
159 host_id = ++g_last_host_id;
160 }
161 */
162 host_id = ++g_last_host_id; 187 host_id = ++g_last_host_id;
163 188
164 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLaunchCause", 189 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLaunchCause",
165 cause, 190 cause,
166 content::CAUSE_FOR_GPU_LAUNCH_MAX_ENUM); 191 content::CAUSE_FOR_GPU_LAUNCH_MAX_ENUM);
167 192
168 GpuProcessHost* host = new GpuProcessHost(host_id); 193 GpuProcessHost* host = new GpuProcessHost(host_id, in_process);
169 if (host->Init()) 194 if (host->Init())
170 return host; 195 return host;
171 196
172 delete host; 197 delete host;
173 return NULL; 198 return NULL;
174 } 199 }
175 200
176 // static 201 // static
177 void GpuProcessHost::SendOnIO(int renderer_id, 202 void GpuProcessHost::SendOnIO(int renderer_id,
178 content::CauseForGpuLaunch cause, 203 content::CauseForGpuLaunch cause,
179 IPC::Message* message) { 204 IPC::Message* message) {
180 BrowserThread::PostTask( 205 BrowserThread::PostTask(
181 BrowserThread::IO, FROM_HERE, 206 BrowserThread::IO, FROM_HERE,
182 NewRunnableFunction( 207 NewRunnableFunction(
183 &SendGpuProcessMessage, renderer_id, cause, message)); 208 &SendGpuProcessMessage, renderer_id, cause, message));
184 } 209 }
185 210
186 // static 211 // static
187 GpuProcessHost* GpuProcessHost::FromID(int host_id) { 212 GpuProcessHost* GpuProcessHost::FromID(int host_id) {
188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 213 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
189 214
190 if (host_id == 0) 215 if (host_id == 0)
191 return NULL; 216 return NULL;
192 217
193 return g_hosts_by_id.Lookup(host_id); 218 return g_hosts_by_id.Lookup(host_id);
194 } 219 }
195 220
196 GpuProcessHost::GpuProcessHost(int host_id) 221 GpuProcessHost::GpuProcessHost(int host_id, bool in_process)
197 : BrowserChildProcessHost(GPU_PROCESS), 222 : BrowserChildProcessHost(GPU_PROCESS),
198 host_id_(host_id), 223 host_id_(host_id),
199 gpu_process_(base::kNullProcessHandle) { 224 gpu_process_(base::kNullProcessHandle),
225 in_process_(in_process) {
200 g_hosts_by_id.AddWithID(this, host_id_); 226 g_hosts_by_id.AddWithID(this, host_id_);
201 if (host_id == 0) 227 if (host_id == 0)
202 gpu_process_ = base::GetCurrentProcessHandle(); 228 gpu_process_ = base::GetCurrentProcessHandle();
203 229
204 // Post a task to create the corresponding GpuProcessHostUIShim. The 230 // Post a task to create the corresponding GpuProcessHostUIShim. The
205 // GpuProcessHostUIShim will be destroyed if either the browser exits, 231 // GpuProcessHostUIShim will be destroyed if either the browser exits,
206 // in which case it calls GpuProcessHostUIShim::DestroyAll, or the 232 // in which case it calls GpuProcessHostUIShim::DestroyAll, or the
207 // GpuProcessHost is destroyed, which happens when the corresponding GPU 233 // GpuProcessHost is destroyed, which happens when the corresponding GPU
208 // process terminates or fails to launch. 234 // process terminates or fails to launch.
209 BrowserThread::PostTask( 235 BrowserThread::PostTask(
(...skipping 20 matching lines...) Expand all
230 BrowserThread::PostTask(BrowserThread::UI, 256 BrowserThread::PostTask(BrowserThread::UI,
231 FROM_HERE, 257 FROM_HERE,
232 NewRunnableFunction(GpuProcessHostUIShim::Destroy, 258 NewRunnableFunction(GpuProcessHostUIShim::Destroy,
233 host_id_)); 259 host_id_));
234 } 260 }
235 261
236 bool GpuProcessHost::Init() { 262 bool GpuProcessHost::Init() {
237 if (!CreateChannel()) 263 if (!CreateChannel())
238 return false; 264 return false;
239 265
240 if (!LaunchGpuProcess()) 266 if (in_process_) {
267 CommandLine::ForCurrentProcess()->AppendSwitch(
268 switches::kDisableGpuWatchdog);
269
270 in_process_gpu_thread_.reset(new GpuThreadWrapper(channel_id()));
271
272 base::Thread::Options options;
273 #if defined(OS_WIN)
274 // On Windows the GPU thread needs to pump the compositor child window's
275 // message loop. TODO(apatrick): make this an IO thread if / when we get rid
276 // of this child window. Unfortunately it might always be necessary for
277 // Windows XP because we cannot share the backing store textures between
278 // processes.
279 options.message_loop_type = MessageLoop::TYPE_UI;
280 #else
281 options.message_loop_type = MessageLoop::TYPE_IO;
282 #endif
283 in_process_gpu_thread_->StartWithOptions(options);
284
285 OnProcessLaunched(); // Fake a callback that the process is ready.
286 } else if (!LaunchGpuProcess())
241 return false; 287 return false;
242 288
243 return Send(new GpuMsg_Initialize()); 289 return Send(new GpuMsg_Initialize());
244 } 290 }
245 291
246 void GpuProcessHost::RouteOnUIThread(const IPC::Message& message) { 292 void GpuProcessHost::RouteOnUIThread(const IPC::Message& message) {
247 BrowserThread::PostTask( 293 BrowserThread::PostTask(
248 BrowserThread::UI, 294 BrowserThread::UI,
249 FROM_HERE, 295 FROM_HERE,
250 new RouteToGpuProcessHostUIShimTask(host_id_, message)); 296 new RouteToGpuProcessHostUIShimTask(host_id_, message));
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 } 466 }
421 467
422 bool GpuProcessHost::CanShutdown() { 468 bool GpuProcessHost::CanShutdown() {
423 return true; 469 return true;
424 } 470 }
425 471
426 void GpuProcessHost::OnProcessLaunched() { 472 void GpuProcessHost::OnProcessLaunched() {
427 // Send the GPU process handle to the UI thread before it has to 473 // Send the GPU process handle to the UI thread before it has to
428 // respond to any requests to establish a GPU channel. The response 474 // respond to any requests to establish a GPU channel. The response
429 // to such requests require that the GPU process handle be known. 475 // to such requests require that the GPU process handle be known.
476
477 base::ProcessHandle child_handle = in_process_ ?
478 base::GetCurrentProcessHandle() : handle();
479
430 #if defined(OS_WIN) 480 #if defined(OS_WIN)
431 DuplicateHandle(base::GetCurrentProcessHandle(), 481 DuplicateHandle(base::GetCurrentProcessHandle(),
432 handle(), 482 child_handle,
433 base::GetCurrentProcessHandle(), 483 base::GetCurrentProcessHandle(),
434 &gpu_process_, 484 &gpu_process_,
435 PROCESS_DUP_HANDLE, 485 PROCESS_DUP_HANDLE,
436 FALSE, 486 FALSE,
437 0); 487 0);
438 #else 488 #else
439 gpu_process_ = handle(); 489 gpu_process_ = child_handle;
440 #endif 490 #endif
441 } 491 }
442 492
443 void GpuProcessHost::OnChildDied() { 493 void GpuProcessHost::OnChildDied() {
444 SendOutstandingReplies(); 494 SendOutstandingReplies();
445 // Located in OnChildDied because OnProcessCrashed suffers from a race 495 // Located in OnChildDied because OnProcessCrashed suffers from a race
446 // condition on Linux. 496 // condition on Linux.
447 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents", 497 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents",
448 DIED_FIRST_TIME + g_gpu_crash_count, 498 DIED_FIRST_TIME + g_gpu_crash_count,
449 GPU_PROCESS_LIFETIME_EVENT_MAX); 499 GPU_PROCESS_LIFETIME_EVENT_MAX);
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
559 CreateCommandBufferCallback* callback, int32 route_id) { 609 CreateCommandBufferCallback* callback, int32 route_id) {
560 scoped_ptr<GpuProcessHost::CreateCommandBufferCallback> 610 scoped_ptr<GpuProcessHost::CreateCommandBufferCallback>
561 wrapped_callback(callback); 611 wrapped_callback(callback);
562 callback->Run(route_id); 612 callback->Run(route_id);
563 } 613 }
564 614
565 void GpuProcessHost::SynchronizeError(SynchronizeCallback* callback) { 615 void GpuProcessHost::SynchronizeError(SynchronizeCallback* callback) {
566 scoped_ptr<SynchronizeCallback> wrapped_callback(callback); 616 scoped_ptr<SynchronizeCallback> wrapped_callback(callback);
567 wrapped_callback->Run(); 617 wrapped_callback->Run();
568 } 618 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698