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

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: add comment Created 9 years, 6 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
« no previous file with comments | « content/browser/gpu/gpu_process_host.h ('k') | content/browser/gpu/gpu_process_host_ui_shim.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 GpuMainThread : public base::Thread {
124 public:
125 explicit GpuMainThread(const std::string& channel_id)
126 : base::Thread("Chrome_InProcGpuThread"),
127 channel_id_(channel_id),
128 gpu_process_(NULL),
129 child_thread_(NULL) {
130 }
131
132 ~GpuMainThread() {
133 Stop();
134 }
135
136 protected:
137 virtual void Init() {
138 // TODO: Currently, ChildProcess supports only a single static instance,
139 // which is a problem in --single-process mode, where both gpu and renderer
140 // should be able to create separate instances.
141 if (GpuProcess::current()) {
142 child_thread_ = new GpuChildThread(channel_id_);
143 } else {
144 gpu_process_ = new GpuProcess();
145 // The process object takes ownership of the thread object, so do not
146 // save and delete the pointer.
147 gpu_process_->set_main_thread(new GpuChildThread(channel_id_));
148 }
149 }
150
151 virtual void CleanUp() {
152 delete gpu_process_;
153 if (child_thread_)
154 delete child_thread_;
155 }
156
157 private:
158 std::string channel_id_;
159 // Deleted in CleanUp() on the gpu thread, so don't use smart pointers.
160 GpuProcess* gpu_process_;
161 GpuChildThread* child_thread_;
162
163 DISALLOW_COPY_AND_ASSIGN(GpuMainThread);
164 };
165
118 // static 166 // static
119 GpuProcessHost* GpuProcessHost::GetForRenderer( 167 GpuProcessHost* GpuProcessHost::GetForRenderer(
120 int renderer_id, content::CauseForGpuLaunch cause) { 168 int renderer_id, content::CauseForGpuLaunch cause) {
121 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 169 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
122 170
123 // Don't grant further access to GPU if it is not allowed. 171 // Don't grant further access to GPU if it is not allowed.
124 GpuDataManager* gpu_data_manager = GpuDataManager::GetInstance(); 172 GpuDataManager* gpu_data_manager = GpuDataManager::GetInstance();
125 if (gpu_data_manager != NULL && !gpu_data_manager->GpuAccessAllowed()) 173 if (gpu_data_manager != NULL && !gpu_data_manager->GpuAccessAllowed())
126 return NULL; 174 return NULL;
127 175
128 // The current policy is to ignore the renderer ID and use a single GPU 176 // 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 177 // process for all renderers. Later this will be extended to allow the
130 // use of multiple GPU processes. 178 // use of multiple GPU processes.
131 if (!g_hosts_by_id.IsEmpty()) { 179 if (!g_hosts_by_id.IsEmpty()) {
132 IDMap<GpuProcessHost>::iterator it(&g_hosts_by_id); 180 IDMap<GpuProcessHost>::iterator it(&g_hosts_by_id);
133 return it.GetCurrentValue(); 181 return it.GetCurrentValue();
134 } 182 }
135 183
136 if (cause == content::CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH) 184 if (cause == content::CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH)
137 return NULL; 185 return NULL;
138 186
139 int host_id; 187 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; 188 host_id = ++g_last_host_id;
163 189
164 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLaunchCause", 190 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLaunchCause",
165 cause, 191 cause,
166 content::CAUSE_FOR_GPU_LAUNCH_MAX_ENUM); 192 content::CAUSE_FOR_GPU_LAUNCH_MAX_ENUM);
167 193
168 GpuProcessHost* host = new GpuProcessHost(host_id); 194 GpuProcessHost* host = new GpuProcessHost(host_id);
169 if (host->Init()) 195 if (host->Init())
170 return host; 196 return host;
171 197
(...skipping 17 matching lines...) Expand all
189 215
190 if (host_id == 0) 216 if (host_id == 0)
191 return NULL; 217 return NULL;
192 218
193 return g_hosts_by_id.Lookup(host_id); 219 return g_hosts_by_id.Lookup(host_id);
194 } 220 }
195 221
196 GpuProcessHost::GpuProcessHost(int host_id) 222 GpuProcessHost::GpuProcessHost(int host_id)
197 : BrowserChildProcessHost(GPU_PROCESS), 223 : BrowserChildProcessHost(GPU_PROCESS),
198 host_id_(host_id), 224 host_id_(host_id),
199 gpu_process_(base::kNullProcessHandle) { 225 gpu_process_(base::kNullProcessHandle),
226 in_process_(false) {
227 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) ||
228 CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU))
229 in_process_ = true;
230
231 // If the 'single GPU process' policy ever changes, we still want to maintain
232 // it for 'gpu thread' mode and only create one instance of host and thread.
233 DCHECK(!in_process_ || g_hosts_by_id.IsEmpty());
234
200 g_hosts_by_id.AddWithID(this, host_id_); 235 g_hosts_by_id.AddWithID(this, host_id_);
201 if (host_id == 0)
202 gpu_process_ = base::GetCurrentProcessHandle();
203 236
204 // Post a task to create the corresponding GpuProcessHostUIShim. The 237 // Post a task to create the corresponding GpuProcessHostUIShim. The
205 // GpuProcessHostUIShim will be destroyed if either the browser exits, 238 // GpuProcessHostUIShim will be destroyed if either the browser exits,
206 // in which case it calls GpuProcessHostUIShim::DestroyAll, or the 239 // in which case it calls GpuProcessHostUIShim::DestroyAll, or the
207 // GpuProcessHost is destroyed, which happens when the corresponding GPU 240 // GpuProcessHost is destroyed, which happens when the corresponding GPU
208 // process terminates or fails to launch. 241 // process terminates or fails to launch.
209 BrowserThread::PostTask( 242 BrowserThread::PostTask(
210 BrowserThread::UI, 243 BrowserThread::UI,
211 FROM_HERE, 244 FROM_HERE,
212 NewRunnableFunction(&GpuProcessHostUIShim::Create, host_id)); 245 NewRunnableFunction(&GpuProcessHostUIShim::Create, host_id));
(...skipping 17 matching lines...) Expand all
230 BrowserThread::PostTask(BrowserThread::UI, 263 BrowserThread::PostTask(BrowserThread::UI,
231 FROM_HERE, 264 FROM_HERE,
232 NewRunnableFunction(GpuProcessHostUIShim::Destroy, 265 NewRunnableFunction(GpuProcessHostUIShim::Destroy,
233 host_id_)); 266 host_id_));
234 } 267 }
235 268
236 bool GpuProcessHost::Init() { 269 bool GpuProcessHost::Init() {
237 if (!CreateChannel()) 270 if (!CreateChannel())
238 return false; 271 return false;
239 272
240 if (!LaunchGpuProcess()) 273 if (in_process_) {
274 CommandLine::ForCurrentProcess()->AppendSwitch(
275 switches::kDisableGpuWatchdog);
276
277 in_process_gpu_thread_.reset(new GpuMainThread(channel_id()));
278
279 base::Thread::Options options;
280 #if defined(OS_WIN)
281 // On Windows the GPU thread needs to pump the compositor child window's
282 // message loop. TODO(apatrick): make this an IO thread if / when we get rid
283 // of this child window. Unfortunately it might always be necessary for
284 // Windows XP because we cannot share the backing store textures between
285 // processes.
286 options.message_loop_type = MessageLoop::TYPE_UI;
287 #else
288 options.message_loop_type = MessageLoop::TYPE_IO;
289 #endif
290 in_process_gpu_thread_->StartWithOptions(options);
291
292 OnProcessLaunched(); // Fake a callback that the process is ready.
293 } else if (!LaunchGpuProcess())
241 return false; 294 return false;
242 295
243 return Send(new GpuMsg_Initialize()); 296 return Send(new GpuMsg_Initialize());
244 } 297 }
245 298
246 void GpuProcessHost::RouteOnUIThread(const IPC::Message& message) { 299 void GpuProcessHost::RouteOnUIThread(const IPC::Message& message) {
247 BrowserThread::PostTask( 300 BrowserThread::PostTask(
248 BrowserThread::UI, 301 BrowserThread::UI,
249 FROM_HERE, 302 FROM_HERE,
250 new RouteToGpuProcessHostUIShimTask(host_id_, message)); 303 new RouteToGpuProcessHostUIShimTask(host_id_, message));
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 } 473 }
421 474
422 bool GpuProcessHost::CanShutdown() { 475 bool GpuProcessHost::CanShutdown() {
423 return true; 476 return true;
424 } 477 }
425 478
426 void GpuProcessHost::OnProcessLaunched() { 479 void GpuProcessHost::OnProcessLaunched() {
427 // Send the GPU process handle to the UI thread before it has to 480 // 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 481 // respond to any requests to establish a GPU channel. The response
429 // to such requests require that the GPU process handle be known. 482 // to such requests require that the GPU process handle be known.
483
484 base::ProcessHandle child_handle = in_process_ ?
485 base::GetCurrentProcessHandle() : handle();
486
430 #if defined(OS_WIN) 487 #if defined(OS_WIN)
431 DuplicateHandle(base::GetCurrentProcessHandle(), 488 DuplicateHandle(base::GetCurrentProcessHandle(),
432 handle(), 489 child_handle,
433 base::GetCurrentProcessHandle(), 490 base::GetCurrentProcessHandle(),
434 &gpu_process_, 491 &gpu_process_,
435 PROCESS_DUP_HANDLE, 492 PROCESS_DUP_HANDLE,
436 FALSE, 493 FALSE,
437 0); 494 0);
438 #else 495 #else
439 gpu_process_ = handle(); 496 gpu_process_ = child_handle;
440 #endif 497 #endif
441 } 498 }
442 499
443 void GpuProcessHost::OnChildDied() { 500 void GpuProcessHost::OnChildDied() {
444 SendOutstandingReplies(); 501 SendOutstandingReplies();
445 // Located in OnChildDied because OnProcessCrashed suffers from a race 502 // Located in OnChildDied because OnProcessCrashed suffers from a race
446 // condition on Linux. 503 // condition on Linux.
447 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents", 504 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents",
448 DIED_FIRST_TIME + g_gpu_crash_count, 505 DIED_FIRST_TIME + g_gpu_crash_count,
449 GPU_PROCESS_LIFETIME_EVENT_MAX); 506 GPU_PROCESS_LIFETIME_EVENT_MAX);
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
559 CreateCommandBufferCallback* callback, int32 route_id) { 616 CreateCommandBufferCallback* callback, int32 route_id) {
560 scoped_ptr<GpuProcessHost::CreateCommandBufferCallback> 617 scoped_ptr<GpuProcessHost::CreateCommandBufferCallback>
561 wrapped_callback(callback); 618 wrapped_callback(callback);
562 callback->Run(route_id); 619 callback->Run(route_id);
563 } 620 }
564 621
565 void GpuProcessHost::SynchronizeError(SynchronizeCallback* callback) { 622 void GpuProcessHost::SynchronizeError(SynchronizeCallback* callback) {
566 scoped_ptr<SynchronizeCallback> wrapped_callback(callback); 623 scoped_ptr<SynchronizeCallback> wrapped_callback(callback);
567 wrapped_callback->Run(); 624 wrapped_callback->Run();
568 } 625 }
OLDNEW
« no previous file with comments | « content/browser/gpu/gpu_process_host.h ('k') | content/browser/gpu/gpu_process_host_ui_shim.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698