| 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 |