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/gfx/gl/gl_implementation.h" |
12 #include "app/win/scoped_com_initializer.h" | 12 #include "app/win/scoped_com_initializer.h" |
13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
| 14 #include "base/debug/trace_event.h" |
14 #include "base/threading/worker_pool.h" | 15 #include "base/threading/worker_pool.h" |
15 #include "build/build_config.h" | 16 #include "build/build_config.h" |
16 #include "chrome/common/child_process.h" | 17 #include "chrome/common/child_process.h" |
17 #include "chrome/common/child_process_logging.h" | 18 #include "chrome/common/child_process_logging.h" |
18 #include "chrome/common/chrome_switches.h" | 19 #include "chrome/common/chrome_switches.h" |
19 #include "chrome/common/gpu_messages.h" | 20 #include "chrome/common/gpu_messages.h" |
20 #include "chrome/gpu/gpu_info_collector.h" | 21 #include "chrome/gpu/gpu_info_collector.h" |
21 #include "chrome/gpu/gpu_watchdog_thread.h" | 22 #include "chrome/gpu/gpu_watchdog_thread.h" |
22 #include "ipc/ipc_channel_handle.h" | 23 #include "ipc/ipc_channel_handle.h" |
23 | 24 |
(...skipping 21 matching lines...) Expand all Loading... |
45 } // namespace | 46 } // namespace |
46 | 47 |
47 GpuThread::GpuThread() { | 48 GpuThread::GpuThread() { |
48 } | 49 } |
49 | 50 |
50 GpuThread::GpuThread(const std::string& channel_id) | 51 GpuThread::GpuThread(const std::string& channel_id) |
51 : ChildThread(channel_id) { | 52 : ChildThread(channel_id) { |
52 } | 53 } |
53 | 54 |
54 GpuThread::~GpuThread() { | 55 GpuThread::~GpuThread() { |
55 logging::SetLogMessageHandler(NULL); | 56 bool single_process = CommandLine::ForCurrentProcess()->HasSwitch( |
| 57 switches::kSingleProcess); |
| 58 if (!single_process) { |
| 59 logging::SetLogMessageHandler(NULL); |
| 60 base::debug::TraceLog::GetInstance()->SetOutputCallback(NULL); |
| 61 } |
56 } | 62 } |
57 | 63 |
58 void GpuThread::Init(const base::Time& process_start_time) { | 64 void GpuThread::Init(const base::Time& process_start_time) { |
59 process_start_time_ = process_start_time; | 65 process_start_time_ = process_start_time; |
60 } | 66 } |
61 | 67 |
62 void GpuThread::RemoveChannel(int renderer_id) { | 68 void GpuThread::RemoveChannel(int renderer_id) { |
63 gpu_channels_.erase(renderer_id); | 69 gpu_channels_.erase(renderer_id); |
64 } | 70 } |
65 | 71 |
66 bool GpuThread::OnControlMessageReceived(const IPC::Message& msg) { | 72 bool GpuThread::OnControlMessageReceived(const IPC::Message& msg) { |
67 bool msg_is_ok = true; | 73 bool msg_is_ok = true; |
68 bool handled = true; | 74 bool handled = true; |
69 IPC_BEGIN_MESSAGE_MAP_EX(GpuThread, msg, msg_is_ok) | 75 IPC_BEGIN_MESSAGE_MAP_EX(GpuThread, msg, msg_is_ok) |
70 IPC_MESSAGE_HANDLER(GpuMsg_Initialize, OnInitialize) | 76 IPC_MESSAGE_HANDLER(GpuMsg_Initialize, OnInitialize) |
71 IPC_MESSAGE_HANDLER(GpuMsg_EstablishChannel, OnEstablishChannel) | 77 IPC_MESSAGE_HANDLER(GpuMsg_EstablishChannel, OnEstablishChannel) |
72 IPC_MESSAGE_HANDLER(GpuMsg_CloseChannel, OnCloseChannel) | 78 IPC_MESSAGE_HANDLER(GpuMsg_CloseChannel, OnCloseChannel) |
73 IPC_MESSAGE_HANDLER(GpuMsg_CreateViewCommandBuffer, | 79 IPC_MESSAGE_HANDLER(GpuMsg_CreateViewCommandBuffer, |
74 OnCreateViewCommandBuffer); | 80 OnCreateViewCommandBuffer); |
75 IPC_MESSAGE_HANDLER(GpuMsg_Synchronize, OnSynchronize) | 81 IPC_MESSAGE_HANDLER(GpuMsg_Synchronize, OnSynchronize) |
76 IPC_MESSAGE_HANDLER(GpuMsg_CollectGraphicsInfo, OnCollectGraphicsInfo) | 82 IPC_MESSAGE_HANDLER(GpuMsg_CollectGraphicsInfo, OnCollectGraphicsInfo) |
| 83 IPC_MESSAGE_HANDLER(GpuMsg_SetTraceEnabled, |
| 84 OnSetTraceEnabled) |
77 #if defined(OS_MACOSX) | 85 #if defined(OS_MACOSX) |
78 IPC_MESSAGE_HANDLER(GpuMsg_AcceleratedSurfaceBuffersSwappedACK, | 86 IPC_MESSAGE_HANDLER(GpuMsg_AcceleratedSurfaceBuffersSwappedACK, |
79 OnAcceleratedSurfaceBuffersSwappedACK) | 87 OnAcceleratedSurfaceBuffersSwappedACK) |
80 IPC_MESSAGE_HANDLER(GpuMsg_DidDestroyAcceleratedSurface, | 88 IPC_MESSAGE_HANDLER(GpuMsg_DidDestroyAcceleratedSurface, |
81 OnDidDestroyAcceleratedSurface) | 89 OnDidDestroyAcceleratedSurface) |
82 #endif | 90 #endif |
83 IPC_MESSAGE_HANDLER(GpuMsg_Crash, OnCrash) | 91 IPC_MESSAGE_HANDLER(GpuMsg_Crash, OnCrash) |
84 IPC_MESSAGE_HANDLER(GpuMsg_Hang, OnHang) | 92 IPC_MESSAGE_HANDLER(GpuMsg_Hang, OnHang) |
85 IPC_MESSAGE_UNHANDLED(handled = false) | 93 IPC_MESSAGE_UNHANDLED(handled = false) |
86 IPC_END_MESSAGE_MAP_EX() | 94 IPC_END_MESSAGE_MAP_EX() |
87 return handled; | 95 return handled; |
88 } | 96 } |
89 | 97 |
90 namespace { | 98 namespace { |
91 | 99 |
92 bool GpuProcessLogMessageHandler(int severity, | 100 bool GpuProcessLogMessageHandler(int severity, |
93 const char* file, int line, | 101 const char* file, int line, |
94 size_t message_start, | 102 size_t message_start, |
95 const std::string& str) { | 103 const std::string& str) { |
96 std::string header = str.substr(0, message_start); | 104 std::string header = str.substr(0, message_start); |
97 std::string message = str.substr(message_start); | 105 std::string message = str.substr(message_start); |
98 ChildThread::current()->Send( | 106 ChildThread::current()->Send( |
99 new GpuHostMsg_OnLogMessage(severity, header, message)); | 107 new GpuHostMsg_OnLogMessage(severity, header, message)); |
100 return false; | 108 return false; |
101 } | 109 } |
102 | 110 |
103 } // namespace | 111 } // namespace |
104 | 112 |
105 void GpuThread::OnInitialize() { | 113 void GpuThread::OnInitialize() { |
106 // Redirect LOG messages to the GpuProcessHost | 114 |
107 bool single_process = CommandLine::ForCurrentProcess()->HasSwitch( | 115 bool single_process = CommandLine::ForCurrentProcess()->HasSwitch( |
108 switches::kSingleProcess); | 116 switches::kSingleProcess); |
109 if (!single_process) | 117 if (!single_process) { |
| 118 // Redirect LOG messages to the GpuProcessHost |
110 logging::SetLogMessageHandler(GpuProcessLogMessageHandler); | 119 logging::SetLogMessageHandler(GpuProcessLogMessageHandler); |
111 | 120 |
| 121 // Forward trace data |
| 122 base::debug::TraceLog::GetInstance()->SetOutputCallback(NewCallback(this, |
| 123 &GpuThread::OnTraceDataCollected)); |
| 124 } |
| 125 |
112 // Load the GL implementation and locate the bindings before starting the GPU | 126 // Load the GL implementation and locate the bindings before starting the GPU |
113 // watchdog because this can take a lot of time and the GPU watchdog might | 127 // watchdog because this can take a lot of time and the GPU watchdog might |
114 // terminate the GPU process. | 128 // terminate the GPU process. |
115 if (!gfx::GLContext::InitializeOneOff()) { | 129 if (!gfx::GLContext::InitializeOneOff()) { |
116 LOG(INFO) << "GLContext::InitializeOneOff failed"; | 130 LOG(INFO) << "GLContext::InitializeOneOff failed"; |
117 MessageLoop::current()->Quit(); | 131 MessageLoop::current()->Quit(); |
118 return; | 132 return; |
119 } | 133 } |
| 134 |
120 gpu_info_collector::CollectGraphicsInfo(&gpu_info_); | 135 gpu_info_collector::CollectGraphicsInfo(&gpu_info_); |
121 child_process_logging::SetGpuInfo(gpu_info_); | 136 child_process_logging::SetGpuInfo(gpu_info_); |
122 LOG(INFO) << "gpu_info_collector::CollectGraphicsInfo complete"; | 137 LOG(INFO) << "gpu_info_collector::CollectGraphicsInfo complete"; |
123 | 138 |
124 // Record initialization only after collecting the GPU info because that can | 139 // Record initialization only after collecting the GPU info because that can |
125 // take a significant amount of time. | 140 // take a significant amount of time. |
126 gpu_info_.SetInitializationTime(base::Time::Now() - process_start_time_); | 141 gpu_info_.SetInitializationTime(base::Time::Now() - process_start_time_); |
127 | 142 |
128 // Note that kNoSandbox will also disable the GPU sandbox. | 143 // Note that kNoSandbox will also disable the GPU sandbox. |
129 bool no_gpu_sandbox = CommandLine::ForCurrentProcess()->HasSwitch( | 144 bool no_gpu_sandbox = CommandLine::ForCurrentProcess()->HasSwitch( |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 void GpuThread::OnCloseChannel(const IPC::ChannelHandle& channel_handle) { | 226 void GpuThread::OnCloseChannel(const IPC::ChannelHandle& channel_handle) { |
212 for (GpuChannelMap::iterator iter = gpu_channels_.begin(); | 227 for (GpuChannelMap::iterator iter = gpu_channels_.begin(); |
213 iter != gpu_channels_.end(); ++iter) { | 228 iter != gpu_channels_.end(); ++iter) { |
214 if (iter->second->GetChannelName() == channel_handle.name) { | 229 if (iter->second->GetChannelName() == channel_handle.name) { |
215 gpu_channels_.erase(iter); | 230 gpu_channels_.erase(iter); |
216 return; | 231 return; |
217 } | 232 } |
218 } | 233 } |
219 } | 234 } |
220 | 235 |
| 236 void GpuThread::OnSetTraceEnabled(bool enabled) { |
| 237 base::debug::TraceLog::GetInstance()->SetEnabled(enabled); |
| 238 if (!enabled) { |
| 239 std::string json_complete("['TRACE_ENDED']"); |
| 240 Send(new GpuHostMsg_TraceDataCollectedRemotely(json_complete)); |
| 241 } |
| 242 } |
| 243 |
221 void GpuThread::OnSynchronize() { | 244 void GpuThread::OnSynchronize() { |
222 Send(new GpuHostMsg_SynchronizeReply()); | 245 Send(new GpuHostMsg_SynchronizeReply()); |
223 } | 246 } |
224 | 247 |
225 void GpuThread::OnCollectGraphicsInfo(GPUInfo::Level level) { | 248 void GpuThread::OnCollectGraphicsInfo(GPUInfo::Level level) { |
226 #if defined(OS_WIN) | 249 #if defined(OS_WIN) |
227 if (level == GPUInfo::kComplete && gpu_info_.level() <= GPUInfo::kPartial) { | 250 if (level == GPUInfo::kComplete && gpu_info_.level() <= GPUInfo::kPartial) { |
228 // Prevent concurrent collection of DirectX diagnostics. | 251 // Prevent concurrent collection of DirectX diagnostics. |
229 gpu_info_.SetLevel(GPUInfo::kCompleting); | 252 gpu_info_.SetLevel(GPUInfo::kCompleting); |
230 | 253 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
274 GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id); | 297 GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id); |
275 if (iter == gpu_channels_.end()) | 298 if (iter == gpu_channels_.end()) |
276 return; | 299 return; |
277 scoped_refptr<GpuChannel> channel = iter->second; | 300 scoped_refptr<GpuChannel> channel = iter->second; |
278 channel->DidDestroySurface(renderer_route_id); | 301 channel->DidDestroySurface(renderer_route_id); |
279 } | 302 } |
280 #endif | 303 #endif |
281 | 304 |
282 void GpuThread::OnCrash() { | 305 void GpuThread::OnCrash() { |
283 LOG(INFO) << "GPU: Simulating GPU crash"; | 306 LOG(INFO) << "GPU: Simulating GPU crash"; |
| 307 TRACE_EVENT_INSTANT0("GPU_CRITICAL", "GpuThread::OnCrash"); |
| 308 |
284 // Good bye, cruel world. | 309 // Good bye, cruel world. |
285 volatile int* it_s_the_end_of_the_world_as_we_know_it = NULL; | 310 volatile int* it_s_the_end_of_the_world_as_we_know_it = NULL; |
286 *it_s_the_end_of_the_world_as_we_know_it = 0xdead; | 311 *it_s_the_end_of_the_world_as_we_know_it = 0xdead; |
287 } | 312 } |
288 | 313 |
289 void GpuThread::OnHang() { | 314 void GpuThread::OnHang() { |
290 LOG(INFO) << "GPU: Simulating GPU hang"; | 315 LOG(INFO) << "GPU: Simulating GPU hang"; |
| 316 TRACE_EVENT_INSTANT0("GPU_CRITICAL", "GpuThread::OnHang"); |
291 for (;;) { | 317 for (;;) { |
292 // Do not sleep here. The GPU watchdog timer tracks the amount of user | 318 // Do not sleep here. The GPU watchdog timer tracks the amount of user |
293 // time this thread is using and it doesn't use much while calling Sleep. | 319 // time this thread is using and it doesn't use much while calling Sleep. |
294 } | 320 } |
295 } | 321 } |
296 | 322 |
| 323 void GpuThread::OnTraceDataCollected(const std::string& json_events) { |
| 324 Send(new GpuHostMsg_TraceDataCollectedRemotely(json_events)); |
| 325 } |
| 326 |
297 #if defined(OS_WIN) | 327 #if defined(OS_WIN) |
298 | 328 |
299 // Runs on a worker thread. The GpuThread never terminates voluntarily so it is | 329 // Runs on a worker thread. The GpuThread never terminates voluntarily so it is |
300 // safe to assume that its message loop is valid. | 330 // safe to assume that its message loop is valid. |
301 void GpuThread::CollectDxDiagnostics(GpuThread* thread) { | 331 void GpuThread::CollectDxDiagnostics(GpuThread* thread) { |
302 app::win::ScopedCOMInitializer com_initializer; | 332 app::win::ScopedCOMInitializer com_initializer; |
303 | 333 |
304 DxDiagNode node; | 334 DxDiagNode node; |
305 gpu_info_collector::GetDxDiagnostics(&node); | 335 gpu_info_collector::GetDxDiagnostics(&node); |
306 | 336 |
307 thread->message_loop()->PostTask( | 337 thread->message_loop()->PostTask( |
308 FROM_HERE, | 338 FROM_HERE, |
309 NewRunnableFunction(&GpuThread::SetDxDiagnostics, thread, node)); | 339 NewRunnableFunction(&GpuThread::SetDxDiagnostics, thread, node)); |
310 } | 340 } |
311 | 341 |
312 // Runs on the GPU thread. | 342 // Runs on the GPU thread. |
313 void GpuThread::SetDxDiagnostics(GpuThread* thread, const DxDiagNode& node) { | 343 void GpuThread::SetDxDiagnostics(GpuThread* thread, const DxDiagNode& node) { |
314 thread->gpu_info_.SetDxDiagnostics(node); | 344 thread->gpu_info_.SetDxDiagnostics(node); |
315 thread->gpu_info_.SetLevel(GPUInfo::kComplete); | 345 thread->gpu_info_.SetLevel(GPUInfo::kComplete); |
316 } | 346 } |
317 | 347 |
318 #endif | 348 #endif |
OLD | NEW |