OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "chrome/gpu/gpu_thread.h" | 5 #include "chrome/gpu/gpu_thread.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "app/gfx/gl/gl_context.h" | 10 #include "app/gfx/gl/gl_context.h" |
| 11 #include "app/gfx/gl/gl_implementation.h" |
11 #include "app/win/scoped_com_initializer.h" | 12 #include "app/win/scoped_com_initializer.h" |
12 #include "base/command_line.h" | 13 #include "base/command_line.h" |
13 #include "base/threading/worker_pool.h" | 14 #include "base/threading/worker_pool.h" |
14 #include "build/build_config.h" | 15 #include "build/build_config.h" |
15 #include "chrome/common/child_process.h" | 16 #include "chrome/common/child_process.h" |
16 #include "chrome/common/child_process_logging.h" | 17 #include "chrome/common/child_process_logging.h" |
| 18 #include "chrome/common/chrome_switches.h" |
17 #include "chrome/common/gpu_messages.h" | 19 #include "chrome/common/gpu_messages.h" |
18 #include "chrome/gpu/gpu_info_collector.h" | 20 #include "chrome/gpu/gpu_info_collector.h" |
| 21 #include "chrome/gpu/gpu_watchdog_thread.h" |
19 #include "ipc/ipc_channel_handle.h" | 22 #include "ipc/ipc_channel_handle.h" |
20 | 23 |
21 GpuThread::GpuThread() { | 24 #if defined(OS_MACOSX) |
| 25 #include "chrome/common/sandbox_init_wrapper.h" |
| 26 #include "chrome/common/sandbox_mac.h" |
| 27 #endif |
| 28 |
| 29 const int kGpuTimeout = 10000; |
| 30 |
| 31 namespace { |
| 32 |
| 33 bool InitializeGpuSandbox() { |
| 34 #if defined(OS_MACOSX) |
| 35 CommandLine* parsed_command_line = CommandLine::ForCurrentProcess(); |
| 36 SandboxInitWrapper sandbox_wrapper; |
| 37 return sandbox_wrapper.InitializeSandbox(*parsed_command_line, |
| 38 switches::kGpuProcess); |
| 39 #else |
| 40 // TODO(port): Create GPU sandbox for linux and windows. |
| 41 return true; |
| 42 #endif |
22 } | 43 } |
23 | 44 |
| 45 } // namespace |
| 46 |
| 47 GpuThread::GpuThread(const CommandLine& command_line) |
| 48 : command_line_(command_line) {} |
| 49 |
24 GpuThread::~GpuThread() { | 50 GpuThread::~GpuThread() { |
25 } | 51 } |
26 | 52 |
27 void GpuThread::Init(const base::Time& process_start_time) { | 53 void GpuThread::Init(const base::Time& process_start_time) { |
28 gpu_info_collector::CollectGraphicsInfo(&gpu_info_); | 54 process_start_time_ = process_start_time; |
29 child_process_logging::SetGpuInfo(gpu_info_); | |
30 | |
31 #if defined(OS_WIN) | |
32 // Asynchronously collect the DirectX diagnostics because this can take a | |
33 // couple of seconds. | |
34 if (!base::WorkerPool::PostTask( | |
35 FROM_HERE, | |
36 NewRunnableFunction(&GpuThread::CollectDxDiagnostics, this), | |
37 true)) { | |
38 // Flag GPU info as complete if the DirectX diagnostics cannot be collected. | |
39 gpu_info_.SetProgress(GPUInfo::kComplete); | |
40 } | |
41 #endif | |
42 | |
43 // Record initialization only after collecting the GPU info because that can | |
44 // take a significant amount of time. | |
45 gpu_info_.SetInitializationTime(base::Time::Now() - process_start_time); | |
46 } | 55 } |
47 | 56 |
48 void GpuThread::RemoveChannel(int renderer_id) { | 57 void GpuThread::RemoveChannel(int renderer_id) { |
49 gpu_channels_.erase(renderer_id); | 58 gpu_channels_.erase(renderer_id); |
50 } | 59 } |
51 | 60 |
52 bool GpuThread::OnControlMessageReceived(const IPC::Message& msg) { | 61 bool GpuThread::OnControlMessageReceived(const IPC::Message& msg) { |
53 bool msg_is_ok = true; | 62 bool msg_is_ok = true; |
54 bool handled = true; | 63 bool handled = true; |
55 IPC_BEGIN_MESSAGE_MAP_EX(GpuThread, msg, msg_is_ok) | 64 IPC_BEGIN_MESSAGE_MAP_EX(GpuThread, msg, msg_is_ok) |
| 65 IPC_MESSAGE_HANDLER(GpuMsg_Initialize, OnInitialize) |
56 IPC_MESSAGE_HANDLER(GpuMsg_EstablishChannel, OnEstablishChannel) | 66 IPC_MESSAGE_HANDLER(GpuMsg_EstablishChannel, OnEstablishChannel) |
57 IPC_MESSAGE_HANDLER(GpuMsg_CloseChannel, OnCloseChannel) | 67 IPC_MESSAGE_HANDLER(GpuMsg_CloseChannel, OnCloseChannel) |
58 IPC_MESSAGE_HANDLER(GpuMsg_Synchronize, OnSynchronize) | 68 IPC_MESSAGE_HANDLER(GpuMsg_Synchronize, OnSynchronize) |
59 IPC_MESSAGE_HANDLER(GpuMsg_CollectGraphicsInfo, OnCollectGraphicsInfo) | 69 IPC_MESSAGE_HANDLER(GpuMsg_CollectGraphicsInfo, OnCollectGraphicsInfo) |
60 #if defined(OS_MACOSX) | 70 #if defined(OS_MACOSX) |
61 IPC_MESSAGE_HANDLER(GpuMsg_AcceleratedSurfaceBuffersSwappedACK, | 71 IPC_MESSAGE_HANDLER(GpuMsg_AcceleratedSurfaceBuffersSwappedACK, |
62 OnAcceleratedSurfaceBuffersSwappedACK) | 72 OnAcceleratedSurfaceBuffersSwappedACK) |
63 IPC_MESSAGE_HANDLER(GpuMsg_DidDestroyAcceleratedSurface, | 73 IPC_MESSAGE_HANDLER(GpuMsg_DidDestroyAcceleratedSurface, |
64 OnDidDestroyAcceleratedSurface) | 74 OnDidDestroyAcceleratedSurface) |
65 #endif | 75 #endif |
66 IPC_MESSAGE_HANDLER(GpuMsg_Crash, OnCrash) | 76 IPC_MESSAGE_HANDLER(GpuMsg_Crash, OnCrash) |
67 IPC_MESSAGE_HANDLER(GpuMsg_Hang, OnHang) | 77 IPC_MESSAGE_HANDLER(GpuMsg_Hang, OnHang) |
68 IPC_MESSAGE_UNHANDLED(handled = false) | 78 IPC_MESSAGE_UNHANDLED(handled = false) |
69 IPC_END_MESSAGE_MAP_EX() | 79 IPC_END_MESSAGE_MAP_EX() |
70 return handled; | 80 return handled; |
71 } | 81 } |
72 | 82 |
| 83 void GpuThread::OnInitialize() { |
| 84 // Load the GL implementation and locate the bindings before starting the GPU |
| 85 // watchdog because this can take a lot of time and the GPU watchdog might |
| 86 // terminate the GPU process. |
| 87 if (!gfx::GLContext::InitializeOneOff()) { |
| 88 MessageLoop::current()->Quit(); |
| 89 return; |
| 90 } |
| 91 gpu_info_collector::CollectGraphicsInfo(&gpu_info_); |
| 92 child_process_logging::SetGpuInfo(gpu_info_); |
| 93 |
| 94 #if defined(OS_WIN) |
| 95 // Asynchronously collect the DirectX diagnostics because this can take a |
| 96 // couple of seconds. |
| 97 if (!base::WorkerPool::PostTask( |
| 98 FROM_HERE, |
| 99 NewRunnableFunction(&GpuThread::CollectDxDiagnostics, this), |
| 100 true)) { |
| 101 // Flag GPU info as complete if the DirectX diagnostics cannot be collected. |
| 102 gpu_info_.SetProgress(GPUInfo::kComplete); |
| 103 } |
| 104 #endif |
| 105 |
| 106 // Record initialization only after collecting the GPU info because that can |
| 107 // take a significant amount of time. |
| 108 gpu_info_.SetInitializationTime(base::Time::Now() - process_start_time_); |
| 109 |
| 110 // Note that kNoSandbox will also disable the GPU sandbox. |
| 111 bool no_gpu_sandbox = command_line_.HasSwitch(switches::kNoGpuSandbox); |
| 112 if (!no_gpu_sandbox) { |
| 113 if (!InitializeGpuSandbox()) { |
| 114 LOG(ERROR) << "Failed to initialize the GPU sandbox"; |
| 115 MessageLoop::current()->Quit(); |
| 116 return; |
| 117 } |
| 118 } else { |
| 119 LOG(ERROR) << "Running without GPU sandbox"; |
| 120 } |
| 121 |
| 122 // In addition to disabling the watchdog if the command line switch is |
| 123 // present, disable it in two other cases. OSMesa is expected to run very |
| 124 // slowly. Also disable the watchdog on valgrind because the code is expected |
| 125 // to run slowly in that case. |
| 126 bool enable_watchdog = |
| 127 !command_line_.HasSwitch(switches::kDisableGpuWatchdog) && |
| 128 gfx::GetGLImplementation() != gfx::kGLImplementationOSMesaGL && |
| 129 !RunningOnValgrind(); |
| 130 |
| 131 // Disable the watchdog in debug builds because they tend to only be run by |
| 132 // developers who will not appreciate the watchdog killing the GPU process. |
| 133 #ifndef NDEBUG |
| 134 enable_watchdog = false; |
| 135 #endif |
| 136 |
| 137 // Disable the watchdog for Windows. It tends to abort when the GPU process |
| 138 // is not hung but still taking a long time to do something. Instead, the |
| 139 // browser process displays a dialog when it notices that the child window |
| 140 // is hung giving the user an opportunity to terminate it. This is the |
| 141 // same mechanism used to abort hung plugins. |
| 142 #if defined(OS_WIN) |
| 143 enable_watchdog = false; |
| 144 #endif |
| 145 |
| 146 // Start the GPU watchdog only after anything that is expected to be time |
| 147 // consuming has completed, otherwise the process is liable to be aborted. |
| 148 if (enable_watchdog) { |
| 149 watchdog_thread_ = new GpuWatchdogThread(kGpuTimeout); |
| 150 watchdog_thread_->Start(); |
| 151 } |
| 152 } |
| 153 |
| 154 void GpuThread::StopWatchdog() { |
| 155 if (watchdog_thread_.get()) { |
| 156 watchdog_thread_->Stop(); |
| 157 } |
| 158 } |
| 159 |
73 void GpuThread::OnEstablishChannel(int renderer_id) { | 160 void GpuThread::OnEstablishChannel(int renderer_id) { |
74 scoped_refptr<GpuChannel> channel; | 161 scoped_refptr<GpuChannel> channel; |
75 IPC::ChannelHandle channel_handle; | 162 IPC::ChannelHandle channel_handle; |
76 GPUInfo gpu_info; | 163 GPUInfo gpu_info; |
77 | 164 |
78 GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id); | 165 GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id); |
79 if (iter == gpu_channels_.end()) | 166 if (iter == gpu_channels_.end()) |
80 channel = new GpuChannel(renderer_id); | 167 channel = new GpuChannel(renderer_id); |
81 else | 168 else |
82 channel = iter->second; | 169 channel = iter->second; |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
166 NewRunnableFunction(&GpuThread::SetDxDiagnostics, thread, node)); | 253 NewRunnableFunction(&GpuThread::SetDxDiagnostics, thread, node)); |
167 } | 254 } |
168 | 255 |
169 // Runs on the GPU thread. | 256 // Runs on the GPU thread. |
170 void GpuThread::SetDxDiagnostics(GpuThread* thread, const DxDiagNode& node) { | 257 void GpuThread::SetDxDiagnostics(GpuThread* thread, const DxDiagNode& node) { |
171 thread->gpu_info_.SetDxDiagnostics(node); | 258 thread->gpu_info_.SetDxDiagnostics(node); |
172 thread->gpu_info_.SetProgress(GPUInfo::kComplete); | 259 thread->gpu_info_.SetProgress(GPUInfo::kComplete); |
173 } | 260 } |
174 | 261 |
175 #endif | 262 #endif |
OLD | NEW |