blob: fbef73987ddb36302520ba56ae31611883f75b47 [file] [log] [blame]
[email protected]f0918242012-02-18 00:30:501// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]c0fc0942010-01-13 00:55:372// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]7a31f7c2011-03-21 23:22:045#include "content/gpu/gpu_child_thread.h"
[email protected]c0fc0942010-01-13 00:55:376
[email protected]80751052011-11-12 17:10:587#include "base/bind.h"
[email protected]ca405d22013-06-25 23:28:558#include "base/lazy_instance.h"
[email protected]ac9ba8fe2010-12-30 18:08:369#include "base/threading/worker_pool.h"
[email protected]274aa5882010-07-15 21:12:2310#include "build/build_config.h"
[email protected]10208ea2013-06-06 20:08:0311#include "content/child/child_process.h"
[email protected]ca405d22013-06-25 23:28:5512#include "content/child/thread_safe_sender.h"
[email protected]202b54ff2011-04-22 21:36:3813#include "content/common/gpu/gpu_messages.h"
[email protected]623c0bd2011-03-12 01:00:4114#include "content/gpu/gpu_watchdog_thread.h"
[email protected]085170ca2012-05-17 20:27:2815#include "content/public/common/content_client.h"
[email protected]c9e2cbbb2012-05-12 21:17:2716#include "content/public/common/content_switches.h"
[email protected]d7b5cc72013-05-23 20:05:0017#include "gpu/config/gpu_info_collector.h"
[email protected]939856a2010-08-24 20:29:0218#include "ipc/ipc_channel_handle.h"
[email protected]8c81e9ecc2012-04-25 00:42:2719#include "ipc/ipc_sync_message_filter.h"
[email protected]c9e2cbbb2012-05-12 21:17:2720#include "ui/gl/gl_implementation.h"
[email protected]7709e712011-01-07 17:57:3121
[email protected]929881f2014-06-20 21:00:3622#if defined(USE_OZONE)
[email protected]929881f2014-06-20 21:00:3623#include "ui/ozone/public/gpu_platform_support.h"
[email protected]f88a8f72014-07-11 18:07:4924#include "ui/ozone/public/ozone_platform.h"
[email protected]929881f2014-06-20 21:00:3625#endif
26
[email protected]eb398192012-10-22 20:16:1927namespace content {
[email protected]7709e712011-01-07 17:57:3128namespace {
29
[email protected]ca405d22013-06-25 23:28:5530static base::LazyInstance<scoped_refptr<ThreadSafeSender> >
31 g_thread_safe_sender = LAZY_INSTANCE_INITIALIZER;
32
[email protected]9158f2f2011-01-27 21:08:5733bool GpuProcessLogMessageHandler(int severity,
34 const char* file, int line,
35 size_t message_start,
36 const std::string& str) {
[email protected]e6ff5a32011-01-31 20:36:2237 std::string header = str.substr(0, message_start);
[email protected]9158f2f2011-01-27 21:08:5738 std::string message = str.substr(message_start);
[email protected]8c81e9ecc2012-04-25 00:42:2739
[email protected]ca405d22013-06-25 23:28:5540 g_thread_safe_sender.Get()->Send(new GpuHostMsg_OnLogMessage(
41 severity, header, message));
[email protected]8c81e9ecc2012-04-25 00:42:2742
[email protected]9158f2f2011-01-27 21:08:5743 return false;
44}
45
[email protected]e6ff5a32011-01-31 20:36:2246} // namespace
[email protected]9158f2f2011-01-27 21:08:5747
[email protected]db6101db2012-10-25 15:20:0848GpuChildThread::GpuChildThread(GpuWatchdogThread* watchdog_thread,
49 bool dead_on_arrival,
[email protected]ec4bda62013-06-14 15:51:0350 const gpu::GPUInfo& gpu_info,
51 const DeferredMessages& deferred_messages)
[email protected]f0918242012-02-18 00:30:5052 : dead_on_arrival_(dead_on_arrival),
[email protected]50749e02013-03-08 04:56:5353 gpu_info_(gpu_info),
[email protected]ec4bda62013-06-14 15:51:0354 deferred_messages_(deferred_messages),
[email protected]50749e02013-03-08 04:56:5355 in_browser_process_(false) {
[email protected]db6101db2012-10-25 15:20:0856 watchdog_thread_ = watchdog_thread;
[email protected]7a31f7c2011-03-21 23:22:0457#if defined(OS_WIN)
[email protected]5abe6302011-12-20 23:44:3258 target_services_ = NULL;
[email protected]7a31f7c2011-03-21 23:22:0459#endif
[email protected]ca405d22013-06-25 23:28:5560 g_thread_safe_sender.Get() = thread_safe_sender();
[email protected]0b2cec62011-07-22 18:13:2861}
[email protected]9158f2f2011-01-27 21:08:5762
[email protected]7a31f7c2011-03-21 23:22:0463GpuChildThread::GpuChildThread(const std::string& channel_id)
[email protected]64860882014-08-04 23:44:1764 : ChildThread(Options(channel_id, false)),
[email protected]50749e02013-03-08 04:56:5365 dead_on_arrival_(false),
66 in_browser_process_(true) {
[email protected]7a31f7c2011-03-21 23:22:0467#if defined(OS_WIN)
68 target_services_ = NULL;
69#endif
[email protected]50749e02013-03-08 04:56:5370 DCHECK(
[email protected]2d3de5452013-01-18 10:03:4071 CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) ||
[email protected]50749e02013-03-08 04:56:5372 CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU));
[email protected]af7c5d92014-02-03 19:53:1573#if !defined(OS_ANDROID)
[email protected]50749e02013-03-08 04:56:5374 // For single process and in-process GPU mode, we need to load and
75 // initialize the GL implementation and locate the GL entry points here.
[email protected]af7c5d92014-02-03 19:53:1576 // On Android, GLSurface::InitializeOneOff() is called from BrowserMainLoop
77 // before getting here. crbug.com/326295
78 if (!gfx::GLSurface::InitializeOneOff())
79 VLOG(1) << "gfx::GLSurface::InitializeOneOff failed";
80#endif
[email protected]ca405d22013-06-25 23:28:5581 g_thread_safe_sender.Get() = thread_safe_sender();
[email protected]7a31f7c2011-03-21 23:22:0482}
83
[email protected]7a31f7c2011-03-21 23:22:0484GpuChildThread::~GpuChildThread() {
[email protected]ce79d8512013-04-22 22:44:4185}
86
87void GpuChildThread::Shutdown() {
[email protected]0e7015f2013-07-23 21:51:1188 ChildThread::Shutdown();
[email protected]7a31f7c2011-03-21 23:22:0489 logging::SetLogMessageHandler(NULL);
90}
91
92void GpuChildThread::Init(const base::Time& process_start_time) {
93 process_start_time_ = process_start_time;
94}
95
96bool GpuChildThread::Send(IPC::Message* msg) {
97 // The GPU process must never send a synchronous IPC message to the browser
[email protected]4c0e289d2011-06-01 03:45:5198 // process. This could result in deadlock.
99 DCHECK(!msg->is_sync());
[email protected]7a31f7c2011-03-21 23:22:04100
101 return ChildThread::Send(msg);
102}
103
104bool GpuChildThread::OnControlMessageReceived(const IPC::Message& msg) {
[email protected]7a31f7c2011-03-21 23:22:04105 bool handled = true;
[email protected]e44d1342014-05-16 21:29:33106 IPC_BEGIN_MESSAGE_MAP(GpuChildThread, msg)
[email protected]7a31f7c2011-03-21 23:22:04107 IPC_MESSAGE_HANDLER(GpuMsg_Initialize, OnInitialize)
108 IPC_MESSAGE_HANDLER(GpuMsg_CollectGraphicsInfo, OnCollectGraphicsInfo)
[email protected]fb246af2012-08-18 03:11:41109 IPC_MESSAGE_HANDLER(GpuMsg_GetVideoMemoryUsageStats,
110 OnGetVideoMemoryUsageStats)
[email protected]184e3f3802011-05-04 20:48:52111 IPC_MESSAGE_HANDLER(GpuMsg_Clean, OnClean)
[email protected]7a31f7c2011-03-21 23:22:04112 IPC_MESSAGE_HANDLER(GpuMsg_Crash, OnCrash)
113 IPC_MESSAGE_HANDLER(GpuMsg_Hang, OnHang)
[email protected]31583a9d2012-11-30 00:37:17114 IPC_MESSAGE_HANDLER(GpuMsg_DisableWatchdog, OnDisableWatchdog)
[email protected]7a31f7c2011-03-21 23:22:04115 IPC_MESSAGE_UNHANDLED(handled = false)
[email protected]e44d1342014-05-16 21:29:33116 IPC_END_MESSAGE_MAP()
[email protected]7a31f7c2011-03-21 23:22:04117
118 if (handled)
119 return true;
120
[email protected]929881f2014-06-20 21:00:36121#if defined(USE_OZONE)
122 if (ui::OzonePlatform::GetInstance()
123 ->GetGpuPlatformSupport()
124 ->OnMessageReceived(msg))
125 return true;
126#endif
127
[email protected]f24a1e2b2011-04-08 01:48:48128 return gpu_channel_manager_.get() &&
129 gpu_channel_manager_->OnMessageReceived(msg);
[email protected]7a31f7c2011-03-21 23:22:04130}
131
132void GpuChildThread::OnInitialize() {
[email protected]0e8cac72014-03-22 00:37:18133 // Record initialization only after collecting the GPU info because that can
134 // take a significant amount of time.
135 gpu_info_.initialization_time = base::Time::Now() - process_start_time_;
[email protected]fd00eee52013-05-24 22:32:28136 Send(new GpuHostMsg_Initialized(!dead_on_arrival_, gpu_info_));
[email protected]ec4bda62013-06-14 15:51:03137 while (!deferred_messages_.empty()) {
138 Send(deferred_messages_.front());
139 deferred_messages_.pop();
140 }
[email protected]96659732012-08-24 01:55:17141
[email protected]0b2cec62011-07-22 18:13:28142 if (dead_on_arrival_) {
[email protected]d7c29422014-03-11 06:08:57143 LOG(ERROR) << "Exiting GPU process due to errors during initialization";
[email protected]dd32b1272013-05-04 14:17:11144 base::MessageLoop::current()->Quit();
[email protected]37cfa2a2012-08-20 20:29:39145 return;
[email protected]0b2cec62011-07-22 18:13:28146 }
147
[email protected]e9875de72013-01-24 01:55:06148#if defined(OS_ANDROID)
[email protected]b38864d2013-05-24 14:42:36149 base::PlatformThread::SetThreadPriority(
150 base::PlatformThread::CurrentHandle(),
151 base::kThreadPriority_Display);
[email protected]e9875de72013-01-24 01:55:06152#endif
153
[email protected]2d9de4112011-05-27 03:18:36154 // We don't need to pipe log messages if we are running the GPU thread in
155 // the browser process.
[email protected]2d3de5452013-01-18 10:03:40156 if (!in_browser_process_)
[email protected]2d9de4112011-05-27 03:18:36157 logging::SetLogMessageHandler(GpuProcessLogMessageHandler);
[email protected]602cf9fda2011-04-22 16:53:30158
[email protected]7a31f7c2011-03-21 23:22:04159 // Defer creation of the render thread. This is to prevent it from handling
160 // IPC messages before the sandbox has been enabled and all other necessary
161 // initialization has succeeded.
[email protected]fc72bb12013-06-02 21:13:46162 gpu_channel_manager_.reset(
[email protected]47953292014-03-13 10:15:37163 new GpuChannelManager(GetRouter(),
[email protected]fc72bb12013-06-02 21:13:46164 watchdog_thread_.get(),
165 ChildProcess::current()->io_message_loop_proxy(),
alexst0269a5c2014-09-10 05:15:12166 ChildProcess::current()->GetShutDownEvent(),
167 channel()));
[email protected]929881f2014-06-20 21:00:36168
169#if defined(USE_OZONE)
170 ui::OzonePlatform::GetInstance()
171 ->GetGpuPlatformSupport()
172 ->OnChannelEstablished(this);
173#endif
[email protected]7709e712011-01-07 17:57:31174}
175
[email protected]7a31f7c2011-03-21 23:22:04176void GpuChildThread::StopWatchdog() {
[email protected]fc72bb12013-06-02 21:13:46177 if (watchdog_thread_.get()) {
[email protected]7709e712011-01-07 17:57:31178 watchdog_thread_->Stop();
179 }
[email protected]c0fc0942010-01-13 00:55:37180}
181
[email protected]7a31f7c2011-03-21 23:22:04182void GpuChildThread::OnCollectGraphicsInfo() {
[email protected]7741f2e2012-12-06 01:29:13183#if defined(OS_WIN)
184 // GPU full info collection should only happen on un-sandboxed GPU process
185 // or single process/in-process gpu mode on Windows.
[email protected]56403c22012-10-04 18:27:04186 CommandLine* command_line = CommandLine::ForCurrentProcess();
[email protected]7741f2e2012-12-06 01:29:13187 DCHECK(command_line->HasSwitch(switches::kDisableGpuSandbox) ||
[email protected]2d3de5452013-01-18 10:03:40188 in_browser_process_);
[email protected]7741f2e2012-12-06 01:29:13189#endif // OS_WIN
[email protected]f3f79b102011-01-27 00:19:37190
[email protected]0e8cac72014-03-22 00:37:18191 gpu::CollectInfoResult result =
192 gpu::CollectContextGraphicsInfo(&gpu_info_);
193 switch (result) {
194 case gpu::kCollectInfoFatalFailure:
195 LOG(ERROR) << "gpu::CollectGraphicsInfo failed (fatal).";
196 // TODO(piman): can we signal overall failure?
197 break;
198 case gpu::kCollectInfoNonFatalFailure:
199 VLOG(1) << "gpu::CollectGraphicsInfo failed (non-fatal).";
200 break;
zmo84eae5e2014-09-05 01:36:23201 case gpu::kCollectInfoNone:
202 NOTREACHED();
203 break;
[email protected]0e8cac72014-03-22 00:37:18204 case gpu::kCollectInfoSuccess:
205 break;
206 }
[email protected]7741f2e2012-12-06 01:29:13207 GetContentClient()->SetGpuInfo(gpu_info_);
[email protected]085170ca2012-05-17 20:27:28208
209#if defined(OS_WIN)
[email protected]87a735d2012-12-07 01:52:44210 // This is slow, but it's the only thing the unsandboxed GPU process does,
211 // and GpuDataManager prevents us from sending multiple collecting requests,
212 // so it's OK to be blocking.
[email protected]d7b5cc72013-05-23 20:05:00213 gpu::GetDxDiagnostics(&gpu_info_.dx_diagnostics);
zmo84eae5e2014-09-05 01:36:23214 gpu_info_.dx_diagnostics_info_state = gpu::kCollectInfoSuccess;
[email protected]87a735d2012-12-07 01:52:44215#endif // OS_WIN
[email protected]085170ca2012-05-17 20:27:28216
[email protected]87a735d2012-12-07 01:52:44217 Send(new GpuHostMsg_GraphicsInfoCollected(gpu_info_));
218
219#if defined(OS_WIN)
[email protected]2d3de5452013-01-18 10:03:40220 if (!in_browser_process_) {
[email protected]87a735d2012-12-07 01:52:44221 // The unsandboxed GPU process fulfilled its duty. Rest in peace.
[email protected]dd32b1272013-05-04 14:17:11222 base::MessageLoop::current()->Quit();
[email protected]085170ca2012-05-17 20:27:28223 }
[email protected]7741f2e2012-12-06 01:29:13224#endif // OS_WIN
[email protected]cadc0502010-09-10 20:27:13225}
[email protected]43ed6282010-09-15 20:07:19226
[email protected]fb246af2012-08-18 03:11:41227void GpuChildThread::OnGetVideoMemoryUsageStats() {
[email protected]eb398192012-10-22 20:16:19228 GPUVideoMemoryUsageStats video_memory_usage_stats;
[email protected]59383c782013-04-17 16:43:27229 if (gpu_channel_manager_)
[email protected]fb246af2012-08-18 03:11:41230 gpu_channel_manager_->gpu_memory_manager()->GetVideoMemoryUsageStats(
[email protected]879c7dfd2012-12-19 21:44:37231 &video_memory_usage_stats);
[email protected]fb246af2012-08-18 03:11:41232 Send(new GpuHostMsg_VideoMemoryUsageStats(video_memory_usage_stats));
233}
234
[email protected]184e3f3802011-05-04 20:48:52235void GpuChildThread::OnClean() {
[email protected]085170ca2012-05-17 20:27:28236 VLOG(1) << "GPU: Removing all contexts";
[email protected]59383c782013-04-17 16:43:27237 if (gpu_channel_manager_)
[email protected]184e3f3802011-05-04 20:48:52238 gpu_channel_manager_->LoseAllContexts();
239}
240
[email protected]7a31f7c2011-03-21 23:22:04241void GpuChildThread::OnCrash() {
[email protected]085170ca2012-05-17 20:27:28242 VLOG(1) << "GPU: Simulating GPU crash";
[email protected]43ed6282010-09-15 20:07:19243 // Good bye, cruel world.
244 volatile int* it_s_the_end_of_the_world_as_we_know_it = NULL;
245 *it_s_the_end_of_the_world_as_we_know_it = 0xdead;
246}
[email protected]259750d2010-09-24 06:14:00247
[email protected]7a31f7c2011-03-21 23:22:04248void GpuChildThread::OnHang() {
[email protected]085170ca2012-05-17 20:27:28249 VLOG(1) << "GPU: Simulating GPU hang";
[email protected]981c1c52010-12-01 20:09:24250 for (;;) {
251 // Do not sleep here. The GPU watchdog timer tracks the amount of user
252 // time this thread is using and it doesn't use much while calling Sleep.
253 }
[email protected]259750d2010-09-24 06:14:00254}
[email protected]41579ae2010-11-15 22:31:26255
[email protected]31583a9d2012-11-30 00:37:17256void GpuChildThread::OnDisableWatchdog() {
257 VLOG(1) << "GPU: Disabling watchdog thread";
[email protected]fc72bb12013-06-02 21:13:46258 if (watchdog_thread_.get()) {
[email protected]31583a9d2012-11-30 00:37:17259 // Disarm the watchdog before shutting down the message loop. This prevents
260 // the future posting of tasks to the message loop.
261 if (watchdog_thread_->message_loop())
262 watchdog_thread_->PostAcknowledge();
263 // Prevent rearming.
264 watchdog_thread_->Stop();
265 }
266}
267
[email protected]eb398192012-10-22 20:16:19268} // namespace content
269