Chromium Code Reviews| 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" |
| 11 #include "base/debug/trace_event.h" | 11 #include "base/debug/trace_event.h" |
| 12 #include "base/memory/ref_counted.h" | 12 #include "base/memory/ref_counted.h" |
| 13 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
| 14 #include "base/process_util.h" | 14 #include "base/process_util.h" |
| 15 #include "base/string_piece.h" | |
| 16 #include "base/threading/thread.h" | 15 #include "base/threading/thread.h" |
| 17 #include "content/browser/browser_child_process_host_impl.h" | 16 #include "content/browser/browser_child_process_host_impl.h" |
| 18 #include "content/browser/gpu/gpu_data_manager_impl.h" | 17 #include "content/browser/gpu/gpu_data_manager_impl.h" |
| 19 #include "content/browser/gpu/gpu_process_host_ui_shim.h" | 18 #include "content/browser/gpu/gpu_process_host_ui_shim.h" |
| 20 #include "content/browser/gpu/gpu_surface_tracker.h" | 19 #include "content/browser/gpu/gpu_surface_tracker.h" |
| 21 #include "content/browser/renderer_host/render_widget_helper.h" | 20 #include "content/browser/renderer_host/render_widget_helper.h" |
| 22 #include "content/browser/renderer_host/render_widget_host_impl.h" | 21 #include "content/browser/renderer_host/render_widget_host_impl.h" |
| 23 #include "content/common/child_process_host_impl.h" | 22 #include "content/common/child_process_host_impl.h" |
| 24 #include "content/common/gpu/gpu_messages.h" | 23 #include "content/common/gpu/gpu_messages.h" |
| 25 #include "content/common/view_messages.h" | 24 #include "content/common/view_messages.h" |
| 26 #include "content/gpu/gpu_child_thread.h" | 25 #include "content/gpu/gpu_child_thread.h" |
| 27 #include "content/gpu/gpu_process.h" | 26 #include "content/gpu/gpu_process.h" |
| 28 #include "content/public/browser/browser_thread.h" | 27 #include "content/public/browser/browser_thread.h" |
| 29 #include "content/public/browser/content_browser_client.h" | 28 #include "content/public/browser/content_browser_client.h" |
| 30 #include "content/public/browser/render_process_host.h" | 29 #include "content/public/browser/render_process_host.h" |
| 31 #include "content/public/browser/render_widget_host_view.h" | 30 #include "content/public/browser/render_widget_host_view.h" |
| 32 #include "content/public/common/content_switches.h" | 31 #include "content/public/common/content_switches.h" |
| 33 #include "content/public/common/result_codes.h" | 32 #include "content/public/common/result_codes.h" |
| 34 #include "gpu/command_buffer/service/gpu_switches.h" | 33 #include "gpu/command_buffer/service/gpu_switches.h" |
| 35 #include "ipc/ipc_channel_handle.h" | 34 #include "ipc/ipc_channel_handle.h" |
| 36 #include "ipc/ipc_switches.h" | 35 #include "ipc/ipc_switches.h" |
| 37 #include "ui/gl/gl_context.h" | |
| 38 #include "ui/gl/gl_implementation.h" | |
| 39 #include "ui/gl/gl_switches.h" | 36 #include "ui/gl/gl_switches.h" |
| 40 | 37 |
| 41 #if defined(TOOLKIT_GTK) | 38 #if defined(TOOLKIT_GTK) |
| 42 #include "ui/gfx/gtk_native_view_id_manager.h" | 39 #include "ui/gfx/gtk_native_view_id_manager.h" |
| 43 #endif | 40 #endif |
| 44 | 41 |
| 45 #if defined(OS_WIN) | 42 #if defined(OS_WIN) |
| 46 #include "ui/surface/accelerated_surface_win.h" | 43 #include "ui/surface/accelerated_surface_win.h" |
| 47 #endif | 44 #endif |
| 48 | 45 |
| 49 namespace content { | 46 namespace content { |
| 50 | 47 |
| 51 bool GpuProcessHost::gpu_enabled_ = true; | 48 bool GpuProcessHost::gpu_enabled_ = true; |
| 52 bool GpuProcessHost::hardware_gpu_enabled_ = true; | 49 bool GpuProcessHost::hardware_gpu_enabled_ = true; |
| 53 | 50 |
| 54 namespace { | 51 namespace { |
| 55 | 52 |
| 56 enum GPUProcessLifetimeEvent { | 53 enum GPUProcessLifetimeEvent { |
| 57 LAUNCHED, | 54 LAUNCHED, |
| 58 DIED_FIRST_TIME, | 55 DIED_FIRST_TIME, |
| 59 DIED_SECOND_TIME, | 56 DIED_SECOND_TIME, |
| 60 DIED_THIRD_TIME, | 57 DIED_THIRD_TIME, |
| 61 DIED_FOURTH_TIME, | 58 DIED_FOURTH_TIME, |
| 62 GPU_PROCESS_LIFETIME_EVENT_MAX = 100 | 59 GPU_PROCESS_LIFETIME_EVENT_MAX = 100 |
| 63 }; | 60 }; |
| 64 | 61 |
| 65 // Indexed by GpuProcessKind. There is one of each kind maximum. This array may | 62 // Indexed by GpuProcessKind. There is one of each kind maximum. This array may |
| 66 // only be accessed from the IO thread. | 63 // only be accessed from the IO thread. |
| 67 static GpuProcessHost *g_gpu_process_hosts[ | 64 GpuProcessHost *g_gpu_process_hosts[ |
|
Zhenyao Mo
2013/01/03 23:04:30
style nit: should be GpuProcessHost* (no space bet
| |
| 68 GpuProcessHost::GPU_PROCESS_KIND_COUNT]; | 65 GpuProcessHost::GPU_PROCESS_KIND_COUNT]; |
| 69 | 66 |
| 70 // Number of times the gpu process has crashed in the current browser session. | |
| 71 static int g_gpu_crash_count = 0; | |
| 72 static int g_gpu_recent_crash_count = 0; | |
| 73 static double g_last_gpu_crash_time; | |
| 74 static bool g_crashed_before = false; | |
| 75 static int g_gpu_software_crash_count = 0; | |
| 76 | |
| 77 // Maximum number of times the gpu process is allowed to crash in a session. | |
| 78 // Once this limit is reached, any request to launch the gpu process will fail. | |
| 79 static const int kGpuMaxCrashCount = 3; | |
| 80 | |
| 81 int g_last_host_id = 0; | |
| 82 | |
| 83 #if defined(TOOLKIT_GTK) | 67 #if defined(TOOLKIT_GTK) |
| 84 | 68 |
| 85 void ReleasePermanentXIDDispatcher(gfx::PluginWindowHandle surface) { | 69 void ReleasePermanentXIDDispatcher(gfx::PluginWindowHandle surface) { |
| 86 GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance(); | 70 GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance(); |
| 87 manager->ReleasePermanentXID(surface); | 71 manager->ReleasePermanentXID(surface); |
| 88 } | 72 } |
| 89 | 73 |
| 90 #endif | 74 #endif |
| 91 | 75 |
| 92 void SendGpuProcessMessage(GpuProcessHost::GpuProcessKind kind, | 76 void SendGpuProcessMessage(GpuProcessHost::GpuProcessKind kind, |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 114 surface_handle, | 98 surface_handle, |
| 115 alive)); | 99 alive)); |
| 116 return; | 100 return; |
| 117 } | 101 } |
| 118 | 102 |
| 119 GpuProcessHost* host = GpuProcessHost::FromID(host_id); | 103 GpuProcessHost* host = GpuProcessHost::FromID(host_id); |
| 120 if (host) { | 104 if (host) { |
| 121 if (alive) { | 105 if (alive) { |
| 122 AcceleratedSurfaceMsg_BufferPresented_Params ack_params; | 106 AcceleratedSurfaceMsg_BufferPresented_Params ack_params; |
| 123 ack_params.sync_point = 0; | 107 ack_params.sync_point = 0; |
| 124 host->Send(new AcceleratedSurfaceMsg_BufferPresented( | 108 host->Send( |
| 125 route_id, ack_params)); | 109 new AcceleratedSurfaceMsg_BufferPresented(route_id, ack_params)); |
| 126 } else { | 110 } else { |
| 127 host->ForceShutdown(); | 111 host->ForceShutdown(); |
| 128 } | 112 } |
| 129 } | 113 } |
| 130 } | 114 } |
| 131 | 115 |
| 132 #if defined(OS_WIN) | 116 #if defined(OS_WIN) |
| 133 // This sends a ViewMsg_SwapBuffers_ACK directly to the renderer process | 117 // This sends a ViewMsg_SwapBuffers_ACK directly to the renderer process |
| 134 // (RenderWidget). This path is currently not used with the threaded compositor. | 118 // (RenderWidget). |
| 135 void AcceleratedSurfaceBuffersSwappedCompletedForRenderer( | 119 void AcceleratedSurfaceBuffersSwappedCompletedForRenderer( |
| 136 int surface_id, | 120 int surface_id, |
| 137 base::TimeTicks timebase, | 121 base::TimeTicks timebase, |
| 138 base::TimeDelta interval) { | 122 base::TimeDelta interval) { |
| 139 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 123 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 140 BrowserThread::PostTask( | 124 BrowserThread::PostTask( |
| 141 BrowserThread::UI, | 125 BrowserThread::UI, |
| 142 FROM_HERE, | 126 FROM_HERE, |
| 143 base::Bind(&AcceleratedSurfaceBuffersSwappedCompletedForRenderer, | 127 base::Bind(&AcceleratedSurfaceBuffersSwappedCompletedForRenderer, |
| 144 surface_id, timebase, interval)); | 128 surface_id, timebase, interval)); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 196 // with --in-process-gpu or --single-process. | 180 // with --in-process-gpu or --single-process. |
| 197 class GpuMainThread : public base::Thread { | 181 class GpuMainThread : public base::Thread { |
| 198 public: | 182 public: |
| 199 explicit GpuMainThread(const std::string& channel_id) | 183 explicit GpuMainThread(const std::string& channel_id) |
| 200 : base::Thread("Chrome_InProcGpuThread"), | 184 : base::Thread("Chrome_InProcGpuThread"), |
| 201 channel_id_(channel_id), | 185 channel_id_(channel_id), |
| 202 gpu_process_(NULL), | 186 gpu_process_(NULL), |
| 203 child_thread_(NULL) { | 187 child_thread_(NULL) { |
| 204 } | 188 } |
| 205 | 189 |
| 206 ~GpuMainThread() { | 190 virtual ~GpuMainThread() { |
| 207 Stop(); | 191 Stop(); |
| 208 } | 192 } |
| 209 | 193 |
| 210 protected: | 194 protected: |
| 211 virtual void Init() { | 195 virtual void Init() OVERRIDE { |
| 212 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess)) { | 196 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess)) { |
| 213 child_thread_ = new GpuChildThread(channel_id_); | 197 child_thread_ = new GpuChildThread(channel_id_); |
| 214 } else { | 198 } else { |
| 215 gpu_process_ = new GpuProcess(); | 199 gpu_process_ = new GpuProcess(); |
| 216 // The process object takes ownership of the thread object, so do not | 200 // The process object takes ownership of the thread object, so do not |
| 217 // save and delete the pointer. | 201 // save and delete the pointer. |
| 218 gpu_process_->set_main_thread(new GpuChildThread(channel_id_)); | 202 gpu_process_->set_main_thread(new GpuChildThread(channel_id_)); |
| 219 } | 203 } |
| 220 } | 204 } |
| 221 | 205 |
| 222 virtual void CleanUp() { | 206 virtual void CleanUp() OVERRIDE { |
| 223 delete gpu_process_; | 207 delete gpu_process_; |
| 224 if (child_thread_) | 208 if (child_thread_) |
| 225 delete child_thread_; | 209 delete child_thread_; |
| 226 } | 210 } |
| 227 | 211 |
| 228 private: | 212 private: |
| 229 std::string channel_id_; | 213 std::string channel_id_; |
| 230 // Deleted in CleanUp() on the gpu thread, so don't use smart pointers. | 214 // Deleted in CleanUp() on the gpu thread, so don't use smart pointers. |
| 231 GpuProcess* gpu_process_; | 215 GpuProcess* gpu_process_; |
| 232 GpuChildThread* child_thread_; | 216 GpuChildThread* child_thread_; |
| 233 | 217 |
| 234 DISALLOW_COPY_AND_ASSIGN(GpuMainThread); | 218 DISALLOW_COPY_AND_ASSIGN(GpuMainThread); |
| 235 }; | 219 }; |
| 236 | 220 |
| 237 // static | 221 // static |
| 238 bool GpuProcessHost::HostIsValid(GpuProcessHost* host) { | 222 bool GpuProcessHost::ValidateHost(GpuProcessHost* host) { |
| 239 if (!host) | 223 if (!host) |
| 240 return false; | 224 return false; |
| 241 | 225 |
| 242 // The Gpu process is invalid if it's not using software, the card is | 226 // The Gpu process is invalid if it's not using software, the card is |
| 243 // blacklisted, and we can kill it and start over. | 227 // blacklisted, and we can kill it and start over. |
| 244 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) || | 228 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) || |
| 245 CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU) || | 229 CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU) || |
| 246 (host->valid_ && | 230 (host->valid_ && |
| 247 (host->software_rendering() || | 231 (host->software_rendering() || |
| 248 !GpuDataManagerImpl::GetInstance()->ShouldUseSoftwareRendering()))) { | 232 !GpuDataManagerImpl::GetInstance()->ShouldUseSoftwareRendering()))) { |
| 249 return true; | 233 return true; |
| 250 } | 234 } |
| 251 | 235 |
| 252 host->ForceShutdown(); | 236 host->ForceShutdown(); |
| 253 return false; | 237 return false; |
| 254 } | 238 } |
| 255 | 239 |
| 256 // static | 240 // static |
| 257 GpuProcessHost* GpuProcessHost::Get(GpuProcessKind kind, | 241 GpuProcessHost* GpuProcessHost::Get(GpuProcessKind kind, |
| 258 CauseForGpuLaunch cause) { | 242 CauseForGpuLaunch cause) { |
| 259 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 243 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 260 | 244 |
| 261 // Don't grant further access to GPU if it is not allowed. | 245 // Don't grant further access to GPU if it is not allowed. |
| 262 GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance(); | 246 GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance(); |
| 263 DCHECK(gpu_data_manager); | 247 DCHECK(gpu_data_manager); |
| 264 if (!gpu_data_manager->GpuAccessAllowed()) | 248 if (!gpu_data_manager->GpuAccessAllowed()) |
| 265 return NULL; | 249 return NULL; |
| 266 | 250 |
| 267 if (g_gpu_process_hosts[kind] && HostIsValid(g_gpu_process_hosts[kind])) | 251 if (g_gpu_process_hosts[kind] && ValidateHost(g_gpu_process_hosts[kind])) |
| 268 return g_gpu_process_hosts[kind]; | 252 return g_gpu_process_hosts[kind]; |
| 269 | 253 |
| 270 if (cause == CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH) | 254 if (cause == CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH) |
| 271 return NULL; | 255 return NULL; |
| 272 | 256 |
| 257 static int last_host_id = 0; | |
| 273 int host_id; | 258 int host_id; |
| 274 host_id = ++g_last_host_id; | 259 host_id = ++last_host_id; |
| 275 | 260 |
| 276 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLaunchCause", | 261 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLaunchCause", |
| 277 cause, | 262 cause, |
| 278 CAUSE_FOR_GPU_LAUNCH_MAX_ENUM); | 263 CAUSE_FOR_GPU_LAUNCH_MAX_ENUM); |
| 279 | 264 |
| 280 GpuProcessHost* host = new GpuProcessHost(host_id, kind); | 265 GpuProcessHost* host = new GpuProcessHost(host_id, kind); |
| 281 if (host->Init()) | 266 if (host->Init()) |
| 282 return host; | 267 return host; |
| 283 | 268 |
| 284 delete host; | 269 delete host; |
| 285 return NULL; | 270 return NULL; |
| 286 } | 271 } |
| 287 | 272 |
| 288 // static | 273 // static |
| 289 void GpuProcessHost::GetProcessHandles( | 274 void GpuProcessHost::GetProcessHandles( |
| 290 const GpuDataManager::GetGpuProcessHandlesCallback& callback) { | 275 const GpuDataManager::GetGpuProcessHandlesCallback& callback) { |
| 291 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | 276 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
| 292 BrowserThread::PostTask( | 277 BrowserThread::PostTask( |
| 293 BrowserThread::IO, | 278 BrowserThread::IO, |
| 294 FROM_HERE, | 279 FROM_HERE, |
| 295 base::Bind(&GpuProcessHost::GetProcessHandles, callback)); | 280 base::Bind(&GpuProcessHost::GetProcessHandles, callback)); |
| 296 return; | 281 return; |
| 297 } | 282 } |
| 298 std::list<base::ProcessHandle> handles; | 283 std::list<base::ProcessHandle> handles; |
| 299 for (int i = 0; i < GPU_PROCESS_KIND_COUNT; ++i) { | 284 for (int i = 0; i < arraysize(g_gpu_process_hosts); ++i) { |
| 300 GpuProcessHost* host = g_gpu_process_hosts[i]; | 285 GpuProcessHost* host = g_gpu_process_hosts[i]; |
| 301 if (host && HostIsValid(host)) | 286 if (host && ValidateHost(host)) |
| 302 handles.push_back(host->process_->GetHandle()); | 287 handles.push_back(host->process_->GetHandle()); |
| 303 } | 288 } |
| 304 BrowserThread::PostTask( | 289 BrowserThread::PostTask( |
| 305 BrowserThread::UI, | 290 BrowserThread::UI, |
| 306 FROM_HERE, | 291 FROM_HERE, |
| 307 base::Bind(callback, handles)); | 292 base::Bind(callback, handles)); |
| 308 } | 293 } |
| 309 | 294 |
| 310 // static | 295 // static |
| 311 void GpuProcessHost::SendOnIO(GpuProcessKind kind, | 296 void GpuProcessHost::SendOnIO(GpuProcessKind kind, |
| 312 CauseForGpuLaunch cause, | 297 CauseForGpuLaunch cause, |
| 313 IPC::Message* message) { | 298 IPC::Message* message) { |
| 314 if (!BrowserThread::PostTask( | 299 if (!BrowserThread::PostTask( |
| 315 BrowserThread::IO, FROM_HERE, | 300 BrowserThread::IO, FROM_HERE, |
| 316 base::Bind( | 301 base::Bind( |
| 317 &SendGpuProcessMessage, kind, cause, message))) { | 302 &SendGpuProcessMessage, kind, cause, message))) { |
| 318 delete message; | 303 delete message; |
| 319 } | 304 } |
| 320 } | 305 } |
| 321 | 306 |
| 322 // static | 307 // static |
| 323 GpuProcessHost* GpuProcessHost::FromID(int host_id) { | 308 GpuProcessHost* GpuProcessHost::FromID(int host_id) { |
| 324 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 309 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 325 | 310 |
| 326 for (int i = 0; i < GPU_PROCESS_KIND_COUNT; ++i) { | 311 for (int i = 0; i < GPU_PROCESS_KIND_COUNT; ++i) { |
| 327 GpuProcessHost* host = g_gpu_process_hosts[i]; | 312 GpuProcessHost* host = g_gpu_process_hosts[i]; |
| 328 if (host && host->host_id_ == host_id && HostIsValid(host)) | 313 if (host && host->host_id_ == host_id && ValidateHost(host)) |
| 329 return host; | 314 return host; |
| 330 } | 315 } |
| 331 | 316 |
| 332 return NULL; | 317 return NULL; |
| 333 } | 318 } |
| 334 | 319 |
| 335 GpuProcessHost::GpuProcessHost(int host_id, GpuProcessKind kind) | 320 GpuProcessHost::GpuProcessHost(int host_id, GpuProcessKind kind) |
| 336 : host_id_(host_id), | 321 : host_id_(host_id), |
| 337 valid_(true), | 322 valid_(true), |
| 338 in_process_(false), | 323 in_process_(false), |
| 339 software_rendering_(false), | 324 software_rendering_(false), |
| 340 kind_(kind), | 325 kind_(kind), |
| 341 process_launched_(false) { | 326 process_launched_(false) { |
| 342 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) || | 327 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) || |
| 343 CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU)) | 328 CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU)) { |
| 344 in_process_ = true; | 329 in_process_ = true; |
| 330 } | |
| 345 | 331 |
| 346 // If the 'single GPU process' policy ever changes, we still want to maintain | 332 // If the 'single GPU process' policy ever changes, we still want to maintain |
| 347 // it for 'gpu thread' mode and only create one instance of host and thread. | 333 // it for 'gpu thread' mode and only create one instance of host and thread. |
| 348 DCHECK(!in_process_ || g_gpu_process_hosts[kind] == NULL); | 334 DCHECK(!in_process_ || g_gpu_process_hosts[kind] == NULL); |
| 349 | 335 |
| 350 g_gpu_process_hosts[kind] = this; | 336 g_gpu_process_hosts[kind] = this; |
| 351 | 337 |
| 352 // Post a task to create the corresponding GpuProcessHostUIShim. The | 338 // Post a task to create the corresponding GpuProcessHostUIShim. The |
| 353 // GpuProcessHostUIShim will be destroyed if either the browser exits, | 339 // GpuProcessHostUIShim will be destroyed if either the browser exits, |
| 354 // in which case it calls GpuProcessHostUIShim::DestroyAll, or the | 340 // in which case it calls GpuProcessHostUIShim::DestroyAll, or the |
| 355 // GpuProcessHost is destroyed, which happens when the corresponding GPU | 341 // GpuProcessHost is destroyed, which happens when the corresponding GPU |
| 356 // process terminates or fails to launch. | 342 // process terminates or fails to launch. |
| 357 BrowserThread::PostTask( | 343 BrowserThread::PostTask( |
| 358 BrowserThread::UI, | 344 BrowserThread::UI, |
| 359 FROM_HERE, | 345 FROM_HERE, |
| 360 base::Bind(base::IgnoreResult(&GpuProcessHostUIShim::Create), host_id)); | 346 base::Bind(base::IgnoreResult(&GpuProcessHostUIShim::Create), host_id)); |
| 361 | 347 |
| 362 process_.reset(new BrowserChildProcessHostImpl(PROCESS_TYPE_GPU, this)); | 348 process_.reset(new BrowserChildProcessHostImpl(PROCESS_TYPE_GPU, this)); |
| 363 } | 349 } |
| 364 | 350 |
| 365 GpuProcessHost::~GpuProcessHost() { | 351 GpuProcessHost::~GpuProcessHost() { |
| 366 DCHECK(CalledOnValidThread()); | 352 DCHECK(CalledOnValidThread()); |
| 367 | 353 |
| 368 SendOutstandingReplies(); | 354 SendOutstandingReplies(); |
| 355 | |
| 356 // Maximum number of times the gpu process is allowed to crash in a session. | |
| 357 // Once this limit is reached, any request to launch the gpu process will | |
| 358 // fail. | |
| 359 const int kGpuMaxCrashCount = 3; | |
| 360 | |
| 361 // Number of times the gpu process has crashed in the current browser session. | |
| 362 static int gpu_crash_count = 0; | |
| 363 static int gpu_recent_crash_count = 0; | |
| 364 static base::Time last_gpu_crash_time; | |
| 365 static bool crashed_before = false; | |
| 366 static int gpu_software_crash_count = 0; | |
| 367 | |
| 369 // Ending only acts as a failure if the GPU process was actually started and | 368 // Ending only acts as a failure if the GPU process was actually started and |
| 370 // was intended for actual rendering (and not just checking caps or other | 369 // was intended for actual rendering (and not just checking caps or other |
| 371 // options). | 370 // options). |
| 372 if (process_launched_ && kind_ == GPU_PROCESS_KIND_SANDBOXED) { | 371 if (process_launched_ && kind_ == GPU_PROCESS_KIND_SANDBOXED) { |
| 373 if (software_rendering_) { | 372 if (software_rendering_) { |
| 374 UMA_HISTOGRAM_ENUMERATION("GPU.SoftwareRendererLifetimeEvents", | 373 UMA_HISTOGRAM_ENUMERATION("GPU.SoftwareRendererLifetimeEvents", |
| 375 DIED_FIRST_TIME + g_gpu_software_crash_count, | 374 DIED_FIRST_TIME + gpu_software_crash_count, |
| 376 GPU_PROCESS_LIFETIME_EVENT_MAX); | 375 GPU_PROCESS_LIFETIME_EVENT_MAX); |
| 377 | 376 |
| 378 if (++g_gpu_software_crash_count >= kGpuMaxCrashCount) { | 377 if (++gpu_software_crash_count >= kGpuMaxCrashCount) { |
| 379 // The software renderer is too unstable to use. Disable it for current | 378 // The software renderer is too unstable to use. Disable it for current |
| 380 // session. | 379 // session. |
| 381 gpu_enabled_ = false; | 380 gpu_enabled_ = false; |
| 382 } | 381 } |
| 383 } else { | 382 } else { |
| 384 ++g_gpu_crash_count; | 383 ++gpu_crash_count; |
| 385 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents", | 384 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents", |
| 386 std::min(DIED_FIRST_TIME + g_gpu_crash_count, | 385 std::min(DIED_FIRST_TIME + gpu_crash_count, |
| 387 GPU_PROCESS_LIFETIME_EVENT_MAX - 1), | 386 GPU_PROCESS_LIFETIME_EVENT_MAX - 1), |
| 388 GPU_PROCESS_LIFETIME_EVENT_MAX); | 387 GPU_PROCESS_LIFETIME_EVENT_MAX); |
| 389 | 388 |
| 390 /* | 389 // Allow about 1 GPU crash per hour to be removed from the crash count, |
| 391 * Allow about 1 GPU crash per hour to be removed from the crash count, | 390 // so very occasional crashes won't eventually add up and prevent the |
| 392 * so very occasional crashes won't eventually add up and prevent the | 391 // GPU process from launching. |
| 393 * GPU process from launching. | 392 ++gpu_recent_crash_count; |
| 394 */ | |
| 395 ++g_gpu_recent_crash_count; | |
| 396 base::Time current_time = base::Time::Now(); | 393 base::Time current_time = base::Time::Now(); |
| 397 if (g_crashed_before) { | 394 if (crashed_before) { |
| 398 base::Time last_crash_time = | 395 int hours_different = (current_time - last_gpu_crash_time).InHours(); |
| 399 base::Time::FromDoubleT(g_last_gpu_crash_time); | 396 gpu_recent_crash_count = |
| 400 int hours_different = (current_time - last_crash_time).InHours(); | 397 std::max(0, gpu_recent_crash_count - hours_different); |
| 401 g_gpu_recent_crash_count = std::max(0, | |
| 402 g_gpu_recent_crash_count - hours_different); | |
| 403 } | 398 } |
| 404 | 399 |
| 405 g_crashed_before = true; | 400 crashed_before = true; |
| 406 g_last_gpu_crash_time = current_time.ToDoubleT(); | 401 last_gpu_crash_time = current_time; |
| 407 | 402 |
| 408 if (g_gpu_recent_crash_count >= kGpuMaxCrashCount) { | 403 if (gpu_recent_crash_count >= kGpuMaxCrashCount) { |
| 409 #if !defined(OS_CHROMEOS) | 404 #if !defined(OS_CHROMEOS) |
| 410 // The gpu process is too unstable to use. Disable it for current | 405 // The gpu process is too unstable to use. Disable it for current |
| 411 // session. | 406 // session. |
| 412 hardware_gpu_enabled_ = false; | 407 hardware_gpu_enabled_ = false; |
| 413 GpuDataManagerImpl::GetInstance()->BlacklistCard(); | 408 GpuDataManagerImpl::GetInstance()->BlacklistCard(); |
| 414 #endif | 409 #endif |
| 415 } | 410 } |
| 416 } | 411 } |
| 417 } | 412 } |
| 418 | 413 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 471 | 466 |
| 472 std::string channel_id = process_->GetHost()->CreateChannel(); | 467 std::string channel_id = process_->GetHost()->CreateChannel(); |
| 473 if (channel_id.empty()) | 468 if (channel_id.empty()) |
| 474 return false; | 469 return false; |
| 475 | 470 |
| 476 if (in_process_) { | 471 if (in_process_) { |
| 477 CommandLine::ForCurrentProcess()->AppendSwitch( | 472 CommandLine::ForCurrentProcess()->AppendSwitch( |
| 478 switches::kDisableGpuWatchdog); | 473 switches::kDisableGpuWatchdog); |
| 479 | 474 |
| 480 in_process_gpu_thread_.reset(new GpuMainThread(channel_id)); | 475 in_process_gpu_thread_.reset(new GpuMainThread(channel_id)); |
| 481 | 476 in_process_gpu_thread_->Start(); |
| 482 base::Thread::Options options; | |
| 483 #if defined(OS_WIN) | |
| 484 // On Windows the GPU thread needs to pump the compositor child window's | |
|
apatrick_chromium
2013/01/03 22:48:26
This thread no longer creates a child window so an
| |
| 485 // message loop. TODO(apatrick): make this an IO thread if / when we get rid | |
| 486 // of this child window. Unfortunately it might always be necessary for | |
| 487 // Windows XP because we cannot share the backing store textures between | |
| 488 // processes. | |
| 489 options.message_loop_type = MessageLoop::TYPE_UI; | |
| 490 #else | |
| 491 options.message_loop_type = MessageLoop::TYPE_IO; | |
| 492 #endif | |
| 493 in_process_gpu_thread_->StartWithOptions(options); | |
| 494 | 477 |
| 495 OnProcessLaunched(); // Fake a callback that the process is ready. | 478 OnProcessLaunched(); // Fake a callback that the process is ready. |
| 496 } else if (!LaunchGpuProcess(channel_id)) { | 479 } else if (!LaunchGpuProcess(channel_id)) { |
| 497 return false; | 480 return false; |
| 498 } | 481 } |
| 499 | 482 |
| 500 if (!Send(new GpuMsg_Initialize())) | 483 if (!Send(new GpuMsg_Initialize())) |
| 501 return false; | 484 return false; |
| 502 | 485 |
| 503 return Send(new GpuMsg_SetVideoMemoryWindowCount( | 486 return Send(new GpuMsg_SetVideoMemoryWindowCount( |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 575 | 558 |
| 576 void GpuProcessHost::EstablishGpuChannel( | 559 void GpuProcessHost::EstablishGpuChannel( |
| 577 int client_id, | 560 int client_id, |
| 578 bool share_context, | 561 bool share_context, |
| 579 const EstablishChannelCallback& callback) { | 562 const EstablishChannelCallback& callback) { |
| 580 DCHECK(CalledOnValidThread()); | 563 DCHECK(CalledOnValidThread()); |
| 581 TRACE_EVENT0("gpu", "GpuProcessHostUIShim::EstablishGpuChannel"); | 564 TRACE_EVENT0("gpu", "GpuProcessHostUIShim::EstablishGpuChannel"); |
| 582 | 565 |
| 583 // If GPU features are already blacklisted, no need to establish the channel. | 566 // If GPU features are already blacklisted, no need to establish the channel. |
| 584 if (!GpuDataManagerImpl::GetInstance()->GpuAccessAllowed()) { | 567 if (!GpuDataManagerImpl::GetInstance()->GpuAccessAllowed()) { |
| 585 EstablishChannelError( | 568 callback.Run(IPC::ChannelHandle(), GPUInfo()); |
| 586 callback, IPC::ChannelHandle(), base::kNullProcessHandle, GPUInfo()); | |
| 587 return; | 569 return; |
| 588 } | 570 } |
| 589 | 571 |
| 590 if (Send(new GpuMsg_EstablishChannel(client_id, share_context))) { | 572 if (Send(new GpuMsg_EstablishChannel(client_id, share_context))) { |
| 591 channel_requests_.push(callback); | 573 channel_requests_.push(callback); |
| 592 } else { | 574 } else { |
| 593 EstablishChannelError( | 575 callback.Run(IPC::ChannelHandle(), GPUInfo()); |
| 594 callback, IPC::ChannelHandle(), | |
| 595 base::kNullProcessHandle, GPUInfo()); | |
| 596 } | 576 } |
| 597 } | 577 } |
| 598 | 578 |
| 599 void GpuProcessHost::CreateViewCommandBuffer( | 579 void GpuProcessHost::CreateViewCommandBuffer( |
| 600 const gfx::GLSurfaceHandle& compositing_surface, | 580 const gfx::GLSurfaceHandle& compositing_surface, |
| 601 int surface_id, | 581 int surface_id, |
| 602 int client_id, | 582 int client_id, |
| 603 const GPUCreateCommandBufferConfig& init_params, | 583 const GPUCreateCommandBufferConfig& init_params, |
| 604 const CreateCommandBufferCallback& callback) { | 584 const CreateCommandBufferCallback& callback) { |
| 605 TRACE_EVENT0("gpu", "GpuProcessHostUIShim::CreateViewCommandBuffer"); | 585 TRACE_EVENT0("gpu", "GpuProcessHostUIShim::CreateViewCommandBuffer"); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 620 #endif // defined(TOOLKIT_GTK) | 600 #endif // defined(TOOLKIT_GTK) |
| 621 | 601 |
| 622 if (!compositing_surface.is_null() && | 602 if (!compositing_surface.is_null() && |
| 623 Send(new GpuMsg_CreateViewCommandBuffer( | 603 Send(new GpuMsg_CreateViewCommandBuffer( |
| 624 compositing_surface, surface_id, client_id, init_params))) { | 604 compositing_surface, surface_id, client_id, init_params))) { |
| 625 create_command_buffer_requests_.push(callback); | 605 create_command_buffer_requests_.push(callback); |
| 626 #if defined(TOOLKIT_GTK) | 606 #if defined(TOOLKIT_GTK) |
| 627 surface_refs_.insert(std::make_pair(surface_id, surface_ref)); | 607 surface_refs_.insert(std::make_pair(surface_id, surface_ref)); |
| 628 #endif | 608 #endif |
| 629 } else { | 609 } else { |
| 630 CreateCommandBufferError(callback, MSG_ROUTING_NONE); | 610 callback.Run(MSG_ROUTING_NONE); |
| 631 } | 611 } |
| 632 } | 612 } |
| 633 | 613 |
| 634 void GpuProcessHost::CreateImage( | 614 void GpuProcessHost::CreateImage(gfx::PluginWindowHandle window, |
| 635 gfx::PluginWindowHandle window, | 615 int client_id, |
| 636 int client_id, | 616 int image_id, |
| 637 int image_id, | 617 const CreateImageCallback& callback) { |
| 638 const CreateImageCallback& callback) { | |
| 639 TRACE_EVENT0("gpu", "GpuProcessHostUIShim::CreateImage"); | 618 TRACE_EVENT0("gpu", "GpuProcessHostUIShim::CreateImage"); |
| 640 | 619 |
| 641 DCHECK(CalledOnValidThread()); | 620 DCHECK(CalledOnValidThread()); |
| 642 | 621 |
| 643 if (Send(new GpuMsg_CreateImage(window, client_id, image_id))) { | 622 if (Send(new GpuMsg_CreateImage(window, client_id, image_id))) { |
| 644 create_image_requests_.push(callback); | 623 create_image_requests_.push(callback); |
| 645 } else { | 624 } else { |
| 646 CreateImageError(callback, gfx::Size()); | 625 callback.Run(gfx::Size()); |
| 647 } | 626 } |
| 648 } | 627 } |
| 649 | 628 |
| 650 void GpuProcessHost::DeleteImage( | 629 void GpuProcessHost::DeleteImage(int client_id, |
| 651 int client_id, | 630 int image_id, |
| 652 int image_id, | 631 int sync_point) { |
| 653 int sync_point) { | |
| 654 TRACE_EVENT0("gpu", "GpuProcessHostUIShim::DeleteImage"); | 632 TRACE_EVENT0("gpu", "GpuProcessHostUIShim::DeleteImage"); |
| 655 | 633 |
| 656 DCHECK(CalledOnValidThread()); | 634 DCHECK(CalledOnValidThread()); |
| 657 | 635 |
| 658 Send(new GpuMsg_DeleteImage(client_id, image_id, sync_point)); | 636 Send(new GpuMsg_DeleteImage(client_id, image_id, sync_point)); |
| 659 } | 637 } |
| 660 | 638 |
| 661 void GpuProcessHost::OnInitialized(bool result) { | 639 void GpuProcessHost::OnInitialized(bool result) { |
| 662 UMA_HISTOGRAM_BOOLEAN("GPU.GPUProcessInitialized", result); | 640 UMA_HISTOGRAM_BOOLEAN("GPU.GPUProcessInitialized", result); |
| 663 } | 641 } |
| 664 | 642 |
| 665 void GpuProcessHost::OnChannelEstablished( | 643 void GpuProcessHost::OnChannelEstablished( |
| 666 const IPC::ChannelHandle& channel_handle) { | 644 const IPC::ChannelHandle& channel_handle) { |
| 667 TRACE_EVENT0("gpu", "GpuProcessHostUIShim::OnChannelEstablished"); | 645 TRACE_EVENT0("gpu", "GpuProcessHostUIShim::OnChannelEstablished"); |
| 668 | 646 |
| 669 EstablishChannelCallback callback = channel_requests_.front(); | 647 EstablishChannelCallback callback = channel_requests_.front(); |
| 670 channel_requests_.pop(); | 648 channel_requests_.pop(); |
| 671 | 649 |
| 672 // Currently if any of the GPU features are blacklisted, we don't establish a | 650 // Currently if any of the GPU features are blacklisted, we don't establish a |
| 673 // GPU channel. | 651 // GPU channel. |
| 674 if (!channel_handle.name.empty() && | 652 if (!channel_handle.name.empty() && |
| 675 !GpuDataManagerImpl::GetInstance()->GpuAccessAllowed()) { | 653 !GpuDataManagerImpl::GetInstance()->GpuAccessAllowed()) { |
| 676 Send(new GpuMsg_CloseChannel(channel_handle)); | 654 Send(new GpuMsg_CloseChannel(channel_handle)); |
| 677 EstablishChannelError(callback, | 655 callback.Run(IPC::ChannelHandle(), GPUInfo()); |
| 678 IPC::ChannelHandle(), | |
| 679 base::kNullProcessHandle, | |
| 680 GPUInfo()); | |
| 681 RouteOnUIThread(GpuHostMsg_OnLogMessage( | 656 RouteOnUIThread(GpuHostMsg_OnLogMessage( |
| 682 logging::LOG_WARNING, | 657 logging::LOG_WARNING, |
| 683 "WARNING", | 658 "WARNING", |
| 684 "Hardware acceleration is unavailable.")); | 659 "Hardware acceleration is unavailable.")); |
| 685 return; | 660 return; |
| 686 } | 661 } |
| 687 | 662 |
| 688 callback.Run(channel_handle, | 663 callback.Run(channel_handle, |
| 689 GpuDataManagerImpl::GetInstance()->GetGPUInfo()); | 664 GpuDataManagerImpl::GetInstance()->GetGPUInfo()); |
| 690 } | 665 } |
| 691 | 666 |
| 692 void GpuProcessHost::OnCommandBufferCreated(const int32 route_id) { | 667 void GpuProcessHost::OnCommandBufferCreated(const int32 route_id) { |
| 693 TRACE_EVENT0("gpu", "GpuProcessHostUIShim::OnCommandBufferCreated"); | 668 TRACE_EVENT0("gpu", "GpuProcessHostUIShim::OnCommandBufferCreated"); |
| 694 | 669 |
| 695 if (!create_command_buffer_requests_.empty()) { | 670 if (create_command_buffer_requests_.empty()) |
| 696 CreateCommandBufferCallback callback = | 671 return; |
| 697 create_command_buffer_requests_.front(); | 672 |
| 698 create_command_buffer_requests_.pop(); | 673 CreateCommandBufferCallback callback = |
| 699 if (route_id == MSG_ROUTING_NONE) | 674 create_command_buffer_requests_.front(); |
|
apatrick_chromium
2013/01/03 22:48:26
Control statement is redundant:
void GpuProcessHo
| |
| 700 CreateCommandBufferError(callback, route_id); | 675 create_command_buffer_requests_.pop(); |
| 701 else | 676 callback.Run(route_id); |
| 702 callback.Run(route_id); | |
| 703 } | |
| 704 } | 677 } |
| 705 | 678 |
| 706 void GpuProcessHost::OnDestroyCommandBuffer(int32 surface_id) { | 679 void GpuProcessHost::OnDestroyCommandBuffer(int32 surface_id) { |
| 707 TRACE_EVENT0("gpu", "GpuProcessHostUIShim::OnDestroyCommandBuffer"); | 680 TRACE_EVENT0("gpu", "GpuProcessHostUIShim::OnDestroyCommandBuffer"); |
| 708 | 681 |
| 709 #if defined(TOOLKIT_GTK) | 682 #if defined(TOOLKIT_GTK) |
| 710 SurfaceRefMap::iterator it = surface_refs_.find(surface_id); | 683 SurfaceRefMap::iterator it = surface_refs_.find(surface_id); |
| 711 if (it != surface_refs_.end()) | 684 if (it != surface_refs_.end()) |
| 712 surface_refs_.erase(it); | 685 surface_refs_.erase(it); |
| 713 #endif // defined(TOOLKIT_GTK) | 686 #endif // defined(TOOLKIT_GTK) |
| 714 } | 687 } |
| 715 | 688 |
| 716 void GpuProcessHost::OnImageCreated(const gfx::Size size) { | 689 void GpuProcessHost::OnImageCreated(const gfx::Size size) { |
| 717 TRACE_EVENT0("gpu", "GpuProcessHost::OnImageCreated"); | 690 TRACE_EVENT0("gpu", "GpuProcessHost::OnImageCreated"); |
| 718 | 691 |
| 719 if (!create_image_requests_.empty()) { | 692 if (!create_image_requests_.empty()) |
| 720 CreateImageCallback callback = create_image_requests_.front(); | 693 return; |
| 721 create_image_requests_.pop(); | 694 |
| 722 callback.Run(size); | 695 CreateImageCallback callback = create_image_requests_.front(); |
| 723 } | 696 create_image_requests_.pop(); |
| 697 callback.Run(size); | |
| 724 } | 698 } |
| 725 | 699 |
| 726 void GpuProcessHost::OnDidCreateOffscreenContext( | 700 void GpuProcessHost::OnDidCreateOffscreenContext(const GURL& url) { |
| 727 const GURL& url) { | |
| 728 urls_with_live_offscreen_contexts_.insert(url); | 701 urls_with_live_offscreen_contexts_.insert(url); |
| 729 } | 702 } |
| 730 | 703 |
| 731 void GpuProcessHost::OnDidLoseContext(bool offscreen, | 704 void GpuProcessHost::OnDidLoseContext(bool offscreen, |
| 732 gpu::error::ContextLostReason reason, | 705 gpu::error::ContextLostReason reason, |
| 733 const GURL& url) { | 706 const GURL& url) { |
| 734 // TODO(kbr): would be nice to see the "offscreen" flag too. | 707 // TODO(kbr): would be nice to see the "offscreen" flag too. |
| 735 TRACE_EVENT2("gpu", "GpuProcessHost::OnDidLoseContext", | 708 TRACE_EVENT2("gpu", "GpuProcessHost::OnDidLoseContext", |
| 736 "reason", reason, | 709 "reason", reason, |
| 737 "url", | 710 "url", |
| 738 url.possibly_invalid_spec()); | 711 url.possibly_invalid_spec()); |
| 739 | 712 |
| 740 if (!offscreen || url.is_empty()) { | 713 if (!offscreen || url.is_empty()) { |
| 741 // Assume that the loss of the compositor's or accelerated canvas' | 714 // Assume that the loss of the compositor's or accelerated canvas' |
| 742 // context is a serious event and blame the loss on all live | 715 // context is a serious event and blame the loss on all live |
| 743 // offscreen contexts. This more robustly handles situations where | 716 // offscreen contexts. This more robustly handles situations where |
| 744 // the GPU process may not actually detect the context loss in the | 717 // the GPU process may not actually detect the context loss in the |
| 745 // offscreen context. | 718 // offscreen context. |
| 746 BlockLiveOffscreenContexts(); | 719 BlockLiveOffscreenContexts(); |
| 747 return; | 720 return; |
| 748 } | 721 } |
| 749 | 722 |
| 750 // Initialization only needed because compiler is stupid. | 723 GpuDataManagerImpl::DomainGuilt guilt; |
| 751 GpuDataManagerImpl::DomainGuilt guilt = | |
| 752 GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN; | |
| 753 | |
| 754 switch (reason) { | 724 switch (reason) { |
| 755 case gpu::error::kGuilty: | 725 case gpu::error::kGuilty: |
| 756 guilt = GpuDataManagerImpl::DOMAIN_GUILT_KNOWN; | 726 guilt = GpuDataManagerImpl::DOMAIN_GUILT_KNOWN; |
| 757 break; | 727 break; |
| 758 case gpu::error::kUnknown: | 728 case gpu::error::kUnknown: |
| 759 guilt = GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN; | 729 guilt = GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN; |
| 760 break; | 730 break; |
| 761 case gpu::error::kInnocent: | 731 case gpu::error::kInnocent: |
| 762 return; | 732 return; |
| 733 default: | |
| 734 NOTREACHED(); | |
|
Zhenyao Mo
2013/01/03 23:04:30
nit: Is this default branch necessary? Without it
apatrick_chromium
2013/01/03 23:12:39
In C++, an enum value is not limited to the member
| |
| 735 return; | |
| 763 } | 736 } |
| 764 | 737 |
| 765 GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs( | 738 GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs(url, guilt); |
| 766 url, guilt); | |
| 767 } | 739 } |
| 768 | 740 |
| 769 void GpuProcessHost::OnDidDestroyOffscreenContext( | 741 void GpuProcessHost::OnDidDestroyOffscreenContext(const GURL& url) { |
| 770 const GURL& url) { | |
| 771 urls_with_live_offscreen_contexts_.erase(url); | 742 urls_with_live_offscreen_contexts_.erase(url); |
| 772 } | 743 } |
| 773 | 744 |
| 774 void GpuProcessHost::OnGpuMemoryUmaStatsReceived( | 745 void GpuProcessHost::OnGpuMemoryUmaStatsReceived( |
| 775 const GPUMemoryUmaStats& stats) { | 746 const GPUMemoryUmaStats& stats) { |
| 776 TRACE_EVENT0("gpu", "GpuProcessHost::OnGpuMemoryUmaStatsReceived"); | 747 TRACE_EVENT0("gpu", "GpuProcessHost::OnGpuMemoryUmaStatsReceived"); |
| 777 uma_memory_stats_ = stats; | 748 uma_memory_stats_ = stats; |
| 778 } | 749 } |
| 779 | 750 |
| 780 #if defined(OS_MACOSX) | 751 #if defined(OS_MACOSX) |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 980 | 951 |
| 981 CommandLine* cmd_line = new CommandLine(exe_path); | 952 CommandLine* cmd_line = new CommandLine(exe_path); |
| 982 cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kGpuProcess); | 953 cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kGpuProcess); |
| 983 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id); | 954 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id); |
| 984 | 955 |
| 985 if (kind_ == GPU_PROCESS_KIND_UNSANDBOXED) | 956 if (kind_ == GPU_PROCESS_KIND_UNSANDBOXED) |
| 986 cmd_line->AppendSwitch(switches::kDisableGpuSandbox); | 957 cmd_line->AppendSwitch(switches::kDisableGpuSandbox); |
| 987 | 958 |
| 988 // Propagate relevant command line switches. | 959 // Propagate relevant command line switches. |
| 989 static const char* const kSwitchNames[] = { | 960 static const char* const kSwitchNames[] = { |
| 961 switches::kCrashOnGpuHang, | |
| 962 switches::kDisableAcceleratedVideoDecode, | |
| 990 switches::kDisableBreakpad, | 963 switches::kDisableBreakpad, |
| 991 switches::kDisableGLMultisampling, | 964 switches::kDisableGLMultisampling, |
| 992 switches::kDisableGpuSandbox, | 965 switches::kDisableGpuSandbox, |
| 993 switches::kReduceGpuSandbox, | |
| 994 switches::kDisableSeccompFilterSandbox, | |
| 995 switches::kEnableGpuSandbox, | |
| 996 switches::kDisableGpuVsync, | 966 switches::kDisableGpuVsync, |
| 997 switches::kDisableGpuWatchdog, | 967 switches::kDisableGpuWatchdog, |
| 998 switches::kDisableImageTransportSurface, | 968 switches::kDisableImageTransportSurface, |
| 999 switches::kDisableAcceleratedVideoDecode, | |
| 1000 switches::kDisableLogging, | 969 switches::kDisableLogging, |
| 970 switches::kDisableSeccompFilterSandbox, | |
| 971 switches::kEnableGpuSandbox, | |
| 1001 switches::kEnableGPUServiceLogging, | 972 switches::kEnableGPUServiceLogging, |
| 1002 switches::kEnableLogging, | 973 switches::kEnableLogging, |
| 1003 #if defined(OS_MACOSX) | 974 switches::kEnableUIReleaseFrontSurface, |
| 1004 switches::kEnableSandboxLogging, | 975 switches::kEnableVirtualGLContexts, |
| 1005 #endif | |
| 1006 switches::kGpuNoContextLost, | 976 switches::kGpuNoContextLost, |
| 1007 switches::kGpuStartupDialog, | 977 switches::kGpuStartupDialog, |
| 1008 switches::kGpuSwitching, | 978 switches::kGpuSwitching, |
| 1009 switches::kLoggingLevel, | 979 switches::kLoggingLevel, |
| 1010 switches::kNoSandbox, | 980 switches::kNoSandbox, |
| 981 switches::kReduceGpuSandbox, | |
| 1011 switches::kTestGLLib, | 982 switches::kTestGLLib, |
| 1012 switches::kTraceStartup, | 983 switches::kTraceStartup, |
| 1013 switches::kV, | 984 switches::kV, |
| 1014 switches::kVModule, | 985 switches::kVModule, |
| 1015 switches::kEnableUIReleaseFrontSurface, | 986 #if defined(OS_MACOSX) |
| 987 switches::kEnableSandboxLogging, | |
| 988 #endif | |
| 1016 #if defined(USE_AURA) | 989 #if defined(USE_AURA) |
| 1017 switches::kUIPrioritizeInGpuProcess, | 990 switches::kUIPrioritizeInGpuProcess, |
| 1018 #endif | 991 #endif |
| 1019 switches::kCrashOnGpuHang, | |
| 1020 switches::kEnableVirtualGLContexts, | |
| 1021 }; | 992 }; |
| 1022 cmd_line->CopySwitchesFrom(browser_command_line, kSwitchNames, | 993 cmd_line->CopySwitchesFrom(browser_command_line, kSwitchNames, |
| 1023 arraysize(kSwitchNames)); | 994 arraysize(kSwitchNames)); |
| 1024 cmd_line->CopySwitchesFrom( | 995 cmd_line->CopySwitchesFrom( |
| 1025 browser_command_line, switches::kGpuSwitches, switches::kNumGpuSwitches); | 996 browser_command_line, switches::kGpuSwitches, switches::kNumGpuSwitches); |
| 1026 | 997 |
| 1027 GetContentClient()->browser()->AppendExtraCommandLineSwitches( | 998 GetContentClient()->browser()->AppendExtraCommandLineSwitches( |
| 1028 cmd_line, process_->GetData().id); | 999 cmd_line, process_->GetData().id); |
| 1029 | 1000 |
| 1030 GpuDataManagerImpl::GetInstance()->AppendGpuCommandLine(cmd_line); | 1001 GpuDataManagerImpl::GetInstance()->AppendGpuCommandLine(cmd_line); |
| 1031 | 1002 |
| 1032 if (cmd_line->HasSwitch(switches::kUseGL)) | 1003 if (cmd_line->HasSwitch(switches::kUseGL)) { |
| 1033 software_rendering_ = | 1004 software_rendering_ = |
| 1034 (cmd_line->GetSwitchValueASCII(switches::kUseGL) == "swiftshader"); | 1005 (cmd_line->GetSwitchValueASCII(switches::kUseGL) == "swiftshader"); |
| 1006 } | |
| 1035 | 1007 |
| 1036 UMA_HISTOGRAM_BOOLEAN("GPU.GPUProcessSoftwareRendering", software_rendering_); | 1008 UMA_HISTOGRAM_BOOLEAN("GPU.GPUProcessSoftwareRendering", software_rendering_); |
| 1037 | 1009 |
| 1038 #if defined(OS_WIN) | 1010 #if defined(OS_WIN) |
| 1039 // Make GoogleDesktopNetwork3.dll think that this is a renderer process so | 1011 // Make GoogleDesktopNetwork3.dll think that the GPU process is a renderer |
| 1040 // it unloads itself. http://crbug/129884 | 1012 // process so the DLL unloads itself. http://crbug/129884 |
| 1041 cmd_line->AppendSwitchASCII("ignored", " --type=renderer "); | 1013 cmd_line->AppendSwitchASCII("ignored", " --type=renderer "); |
| 1042 #endif | 1014 #endif |
| 1043 | 1015 |
| 1044 // If specified, prepend a launcher program to the command line. | 1016 // If specified, prepend a launcher program to the command line. |
| 1045 if (!gpu_launcher.empty()) | 1017 if (!gpu_launcher.empty()) |
| 1046 cmd_line->PrependWrapper(gpu_launcher); | 1018 cmd_line->PrependWrapper(gpu_launcher); |
| 1047 | 1019 |
| 1048 process_->Launch( | 1020 process_->Launch( |
| 1049 #if defined(OS_WIN) | 1021 #if defined(OS_WIN) |
| 1050 FilePath(), | 1022 FilePath(), |
| 1051 #elif defined(OS_POSIX) | 1023 #elif defined(OS_POSIX) |
| 1052 false, // Never use the zygote (GPU plugin can't be sandboxed). | 1024 false, |
| 1053 base::EnvironmentVector(), | 1025 base::EnvironmentVector(), |
| 1054 #endif | 1026 #endif |
| 1055 cmd_line); | 1027 cmd_line); |
| 1056 process_launched_ = true; | 1028 process_launched_ = true; |
| 1057 | 1029 |
| 1058 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents", | 1030 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents", |
| 1059 LAUNCHED, GPU_PROCESS_LIFETIME_EVENT_MAX); | 1031 LAUNCHED, GPU_PROCESS_LIFETIME_EVENT_MAX); |
| 1060 return true; | 1032 return true; |
| 1061 } | 1033 } |
| 1062 | 1034 |
| 1063 void GpuProcessHost::SendOutstandingReplies() { | 1035 void GpuProcessHost::SendOutstandingReplies() { |
| 1064 // First send empty channel handles for all EstablishChannel requests. | 1036 // First send empty channel handles for all EstablishChannel requests. |
| 1065 while (!channel_requests_.empty()) { | 1037 while (!channel_requests_.empty()) { |
| 1066 EstablishChannelCallback callback = channel_requests_.front(); | 1038 EstablishChannelCallback callback = channel_requests_.front(); |
| 1067 channel_requests_.pop(); | 1039 channel_requests_.pop(); |
| 1068 EstablishChannelError(callback, | 1040 callback.Run(IPC::ChannelHandle(), GPUInfo()); |
| 1069 IPC::ChannelHandle(), | |
| 1070 base::kNullProcessHandle, | |
| 1071 GPUInfo()); | |
| 1072 } | 1041 } |
| 1073 } | 1042 } |
| 1074 | 1043 |
| 1075 void GpuProcessHost::EstablishChannelError( | |
| 1076 const EstablishChannelCallback& callback, | |
| 1077 const IPC::ChannelHandle& channel_handle, | |
| 1078 base::ProcessHandle renderer_process_for_gpu, | |
| 1079 const GPUInfo& gpu_info) { | |
| 1080 callback.Run(channel_handle, gpu_info); | |
| 1081 } | |
| 1082 | |
| 1083 void GpuProcessHost::CreateCommandBufferError( | |
| 1084 const CreateCommandBufferCallback& callback, int32 route_id) { | |
| 1085 callback.Run(route_id); | |
| 1086 } | |
| 1087 | |
| 1088 void GpuProcessHost::CreateImageError( | |
| 1089 const CreateImageCallback& callback, const gfx::Size size) { | |
| 1090 callback.Run(size); | |
| 1091 } | |
| 1092 | |
| 1093 void GpuProcessHost::BlockLiveOffscreenContexts() { | 1044 void GpuProcessHost::BlockLiveOffscreenContexts() { |
| 1094 for (std::multiset<GURL>::iterator iter = | 1045 for (std::multiset<GURL>::iterator iter = |
| 1095 urls_with_live_offscreen_contexts_.begin(); | 1046 urls_with_live_offscreen_contexts_.begin(); |
| 1096 iter != urls_with_live_offscreen_contexts_.end(); ++iter) { | 1047 iter != urls_with_live_offscreen_contexts_.end(); ++iter) { |
| 1097 GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs( | 1048 GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs( |
| 1098 *iter, GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN); | 1049 *iter, GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN); |
| 1099 } | 1050 } |
| 1100 } | 1051 } |
| 1101 | 1052 |
| 1102 } // namespace content | 1053 } // namespace content |
| OLD | NEW |