blob: 1064a70adc111cae2969eafde6b6368b4335d886 [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"
ccameron17d51092014-10-24 22:17:0721#include "ui/gl/gpu_switching_manager.h"
[email protected]7709e712011-01-07 17:57:3122
[email protected]929881f2014-06-20 21:00:3623#if defined(USE_OZONE)
[email protected]929881f2014-06-20 21:00:3624#include "ui/ozone/public/gpu_platform_support.h"
[email protected]f88a8f72014-07-11 18:07:4925#include "ui/ozone/public/ozone_platform.h"
[email protected]929881f2014-06-20 21:00:3626#endif
27
[email protected]eb398192012-10-22 20:16:1928namespace content {
[email protected]7709e712011-01-07 17:57:3129namespace {
30
[email protected]ca405d22013-06-25 23:28:5531static base::LazyInstance<scoped_refptr<ThreadSafeSender> >
32 g_thread_safe_sender = LAZY_INSTANCE_INITIALIZER;
33
[email protected]9158f2f2011-01-27 21:08:5734bool GpuProcessLogMessageHandler(int severity,
35 const char* file, int line,
36 size_t message_start,
37 const std::string& str) {
[email protected]e6ff5a32011-01-31 20:36:2238 std::string header = str.substr(0, message_start);
[email protected]9158f2f2011-01-27 21:08:5739 std::string message = str.substr(message_start);
[email protected]8c81e9ecc2012-04-25 00:42:2740
[email protected]ca405d22013-06-25 23:28:5541 g_thread_safe_sender.Get()->Send(new GpuHostMsg_OnLogMessage(
42 severity, header, message));
[email protected]8c81e9ecc2012-04-25 00:42:2743
[email protected]9158f2f2011-01-27 21:08:5744 return false;
45}
46
jam8a021512a2015-02-03 18:16:0847ChildThreadImpl::Options GetOptions() {
48 ChildThreadImpl::Options options;
alexst6154ce772015-01-21 12:41:4149
50#if defined(USE_OZONE)
51 IPC::MessageFilter* message_filter = ui::OzonePlatform::GetInstance()
52 ->GetGpuPlatformSupport()
53 ->GetMessageFilter();
54 if (message_filter)
55 options.startup_filters.push_back(message_filter);
56#endif
57
58 return options;
59}
60
[email protected]e6ff5a32011-01-31 20:36:2261} // namespace
[email protected]9158f2f2011-01-27 21:08:5762
[email protected]db6101db2012-10-25 15:20:0863GpuChildThread::GpuChildThread(GpuWatchdogThread* watchdog_thread,
64 bool dead_on_arrival,
[email protected]ec4bda62013-06-14 15:51:0365 const gpu::GPUInfo& gpu_info,
66 const DeferredMessages& deferred_messages)
jam8a021512a2015-02-03 18:16:0867 : ChildThreadImpl(GetOptions()),
alexst6154ce772015-01-21 12:41:4168 dead_on_arrival_(dead_on_arrival),
[email protected]50749e02013-03-08 04:56:5369 gpu_info_(gpu_info),
[email protected]ec4bda62013-06-14 15:51:0370 deferred_messages_(deferred_messages),
[email protected]50749e02013-03-08 04:56:5371 in_browser_process_(false) {
[email protected]db6101db2012-10-25 15:20:0872 watchdog_thread_ = watchdog_thread;
[email protected]7a31f7c2011-03-21 23:22:0473#if defined(OS_WIN)
[email protected]5abe6302011-12-20 23:44:3274 target_services_ = NULL;
[email protected]7a31f7c2011-03-21 23:22:0475#endif
[email protected]ca405d22013-06-25 23:28:5576 g_thread_safe_sender.Get() = thread_safe_sender();
[email protected]0b2cec62011-07-22 18:13:2877}
[email protected]9158f2f2011-01-27 21:08:5778
[email protected]7a31f7c2011-03-21 23:22:0479GpuChildThread::GpuChildThread(const std::string& channel_id)
jam8a021512a2015-02-03 18:16:0880 : ChildThreadImpl(Options(channel_id, false)),
[email protected]50749e02013-03-08 04:56:5381 dead_on_arrival_(false),
82 in_browser_process_(true) {
[email protected]7a31f7c2011-03-21 23:22:0483#if defined(OS_WIN)
84 target_services_ = NULL;
85#endif
avi83883c82014-12-23 00:08:4986 DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
87 switches::kSingleProcess) ||
88 base::CommandLine::ForCurrentProcess()->HasSwitch(
89 switches::kInProcessGPU));
[email protected]af7c5d92014-02-03 19:53:1590#if !defined(OS_ANDROID)
[email protected]50749e02013-03-08 04:56:5391 // For single process and in-process GPU mode, we need to load and
92 // initialize the GL implementation and locate the GL entry points here.
[email protected]af7c5d92014-02-03 19:53:1593 // On Android, GLSurface::InitializeOneOff() is called from BrowserMainLoop
94 // before getting here. crbug.com/326295
95 if (!gfx::GLSurface::InitializeOneOff())
96 VLOG(1) << "gfx::GLSurface::InitializeOneOff failed";
97#endif
[email protected]ca405d22013-06-25 23:28:5598 g_thread_safe_sender.Get() = thread_safe_sender();
[email protected]7a31f7c2011-03-21 23:22:0499}
100
[email protected]7a31f7c2011-03-21 23:22:04101GpuChildThread::~GpuChildThread() {
[email protected]ce79d8512013-04-22 22:44:41102}
103
104void GpuChildThread::Shutdown() {
jam8a021512a2015-02-03 18:16:08105 ChildThreadImpl::Shutdown();
[email protected]7a31f7c2011-03-21 23:22:04106 logging::SetLogMessageHandler(NULL);
107}
108
109void GpuChildThread::Init(const base::Time& process_start_time) {
110 process_start_time_ = process_start_time;
111}
112
113bool GpuChildThread::Send(IPC::Message* msg) {
114 // The GPU process must never send a synchronous IPC message to the browser
[email protected]4c0e289d2011-06-01 03:45:51115 // process. This could result in deadlock.
116 DCHECK(!msg->is_sync());
[email protected]7a31f7c2011-03-21 23:22:04117
jam8a021512a2015-02-03 18:16:08118 return ChildThreadImpl::Send(msg);
[email protected]7a31f7c2011-03-21 23:22:04119}
120
121bool GpuChildThread::OnControlMessageReceived(const IPC::Message& msg) {
[email protected]7a31f7c2011-03-21 23:22:04122 bool handled = true;
[email protected]e44d1342014-05-16 21:29:33123 IPC_BEGIN_MESSAGE_MAP(GpuChildThread, msg)
[email protected]7a31f7c2011-03-21 23:22:04124 IPC_MESSAGE_HANDLER(GpuMsg_Initialize, OnInitialize)
125 IPC_MESSAGE_HANDLER(GpuMsg_CollectGraphicsInfo, OnCollectGraphicsInfo)
[email protected]fb246af2012-08-18 03:11:41126 IPC_MESSAGE_HANDLER(GpuMsg_GetVideoMemoryUsageStats,
127 OnGetVideoMemoryUsageStats)
[email protected]184e3f3802011-05-04 20:48:52128 IPC_MESSAGE_HANDLER(GpuMsg_Clean, OnClean)
[email protected]7a31f7c2011-03-21 23:22:04129 IPC_MESSAGE_HANDLER(GpuMsg_Crash, OnCrash)
130 IPC_MESSAGE_HANDLER(GpuMsg_Hang, OnHang)
[email protected]31583a9d2012-11-30 00:37:17131 IPC_MESSAGE_HANDLER(GpuMsg_DisableWatchdog, OnDisableWatchdog)
ccameron17d51092014-10-24 22:17:07132 IPC_MESSAGE_HANDLER(GpuMsg_GpuSwitched, OnGpuSwitched)
[email protected]7a31f7c2011-03-21 23:22:04133 IPC_MESSAGE_UNHANDLED(handled = false)
[email protected]e44d1342014-05-16 21:29:33134 IPC_END_MESSAGE_MAP()
[email protected]7a31f7c2011-03-21 23:22:04135
136 if (handled)
137 return true;
138
[email protected]929881f2014-06-20 21:00:36139#if defined(USE_OZONE)
140 if (ui::OzonePlatform::GetInstance()
141 ->GetGpuPlatformSupport()
142 ->OnMessageReceived(msg))
143 return true;
144#endif
145
[email protected]f24a1e2b2011-04-08 01:48:48146 return gpu_channel_manager_.get() &&
147 gpu_channel_manager_->OnMessageReceived(msg);
[email protected]7a31f7c2011-03-21 23:22:04148}
149
150void GpuChildThread::OnInitialize() {
[email protected]0e8cac72014-03-22 00:37:18151 // Record initialization only after collecting the GPU info because that can
152 // take a significant amount of time.
153 gpu_info_.initialization_time = base::Time::Now() - process_start_time_;
[email protected]fd00eee52013-05-24 22:32:28154 Send(new GpuHostMsg_Initialized(!dead_on_arrival_, gpu_info_));
[email protected]ec4bda62013-06-14 15:51:03155 while (!deferred_messages_.empty()) {
156 Send(deferred_messages_.front());
157 deferred_messages_.pop();
158 }
[email protected]96659732012-08-24 01:55:17159
[email protected]0b2cec62011-07-22 18:13:28160 if (dead_on_arrival_) {
[email protected]d7c29422014-03-11 06:08:57161 LOG(ERROR) << "Exiting GPU process due to errors during initialization";
[email protected]dd32b1272013-05-04 14:17:11162 base::MessageLoop::current()->Quit();
[email protected]37cfa2a2012-08-20 20:29:39163 return;
[email protected]0b2cec62011-07-22 18:13:28164 }
165
[email protected]e9875de72013-01-24 01:55:06166#if defined(OS_ANDROID)
[email protected]b38864d2013-05-24 14:42:36167 base::PlatformThread::SetThreadPriority(
168 base::PlatformThread::CurrentHandle(),
169 base::kThreadPriority_Display);
[email protected]e9875de72013-01-24 01:55:06170#endif
171
[email protected]2d9de4112011-05-27 03:18:36172 // We don't need to pipe log messages if we are running the GPU thread in
173 // the browser process.
[email protected]2d3de5452013-01-18 10:03:40174 if (!in_browser_process_)
[email protected]2d9de4112011-05-27 03:18:36175 logging::SetLogMessageHandler(GpuProcessLogMessageHandler);
[email protected]602cf9fda2011-04-22 16:53:30176
[email protected]7a31f7c2011-03-21 23:22:04177 // Defer creation of the render thread. This is to prevent it from handling
178 // IPC messages before the sandbox has been enabled and all other necessary
179 // initialization has succeeded.
[email protected]fc72bb12013-06-02 21:13:46180 gpu_channel_manager_.reset(
[email protected]47953292014-03-13 10:15:37181 new GpuChannelManager(GetRouter(),
[email protected]fc72bb12013-06-02 21:13:46182 watchdog_thread_.get(),
183 ChildProcess::current()->io_message_loop_proxy(),
alexst0269a5c2014-09-10 05:15:12184 ChildProcess::current()->GetShutDownEvent(),
185 channel()));
[email protected]929881f2014-06-20 21:00:36186
187#if defined(USE_OZONE)
alexst6154ce772015-01-21 12:41:41188 ui::OzonePlatform::GetInstance()
189 ->GetGpuPlatformSupport()
190 ->OnChannelEstablished(this);
[email protected]929881f2014-06-20 21:00:36191#endif
[email protected]7709e712011-01-07 17:57:31192}
193
[email protected]7a31f7c2011-03-21 23:22:04194void GpuChildThread::StopWatchdog() {
[email protected]fc72bb12013-06-02 21:13:46195 if (watchdog_thread_.get()) {
[email protected]7709e712011-01-07 17:57:31196 watchdog_thread_->Stop();
197 }
[email protected]c0fc0942010-01-13 00:55:37198}
199
[email protected]7a31f7c2011-03-21 23:22:04200void GpuChildThread::OnCollectGraphicsInfo() {
[email protected]7741f2e2012-12-06 01:29:13201#if defined(OS_WIN)
202 // GPU full info collection should only happen on un-sandboxed GPU process
203 // or single process/in-process gpu mode on Windows.
avi83883c82014-12-23 00:08:49204 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
[email protected]7741f2e2012-12-06 01:29:13205 DCHECK(command_line->HasSwitch(switches::kDisableGpuSandbox) ||
[email protected]2d3de5452013-01-18 10:03:40206 in_browser_process_);
[email protected]7741f2e2012-12-06 01:29:13207#endif // OS_WIN
[email protected]f3f79b102011-01-27 00:19:37208
[email protected]0e8cac72014-03-22 00:37:18209 gpu::CollectInfoResult result =
210 gpu::CollectContextGraphicsInfo(&gpu_info_);
211 switch (result) {
212 case gpu::kCollectInfoFatalFailure:
213 LOG(ERROR) << "gpu::CollectGraphicsInfo failed (fatal).";
214 // TODO(piman): can we signal overall failure?
215 break;
216 case gpu::kCollectInfoNonFatalFailure:
anujk.sharma98e81a12014-11-14 04:54:21217 DVLOG(1) << "gpu::CollectGraphicsInfo failed (non-fatal).";
[email protected]0e8cac72014-03-22 00:37:18218 break;
zmo84eae5e2014-09-05 01:36:23219 case gpu::kCollectInfoNone:
220 NOTREACHED();
221 break;
[email protected]0e8cac72014-03-22 00:37:18222 case gpu::kCollectInfoSuccess:
223 break;
224 }
[email protected]7741f2e2012-12-06 01:29:13225 GetContentClient()->SetGpuInfo(gpu_info_);
[email protected]085170ca2012-05-17 20:27:28226
227#if defined(OS_WIN)
[email protected]87a735d2012-12-07 01:52:44228 // This is slow, but it's the only thing the unsandboxed GPU process does,
229 // and GpuDataManager prevents us from sending multiple collecting requests,
230 // so it's OK to be blocking.
[email protected]d7b5cc72013-05-23 20:05:00231 gpu::GetDxDiagnostics(&gpu_info_.dx_diagnostics);
zmo84eae5e2014-09-05 01:36:23232 gpu_info_.dx_diagnostics_info_state = gpu::kCollectInfoSuccess;
[email protected]87a735d2012-12-07 01:52:44233#endif // OS_WIN
[email protected]085170ca2012-05-17 20:27:28234
[email protected]87a735d2012-12-07 01:52:44235 Send(new GpuHostMsg_GraphicsInfoCollected(gpu_info_));
236
237#if defined(OS_WIN)
[email protected]2d3de5452013-01-18 10:03:40238 if (!in_browser_process_) {
[email protected]87a735d2012-12-07 01:52:44239 // The unsandboxed GPU process fulfilled its duty. Rest in peace.
[email protected]dd32b1272013-05-04 14:17:11240 base::MessageLoop::current()->Quit();
[email protected]085170ca2012-05-17 20:27:28241 }
[email protected]7741f2e2012-12-06 01:29:13242#endif // OS_WIN
[email protected]cadc0502010-09-10 20:27:13243}
[email protected]43ed6282010-09-15 20:07:19244
[email protected]fb246af2012-08-18 03:11:41245void GpuChildThread::OnGetVideoMemoryUsageStats() {
[email protected]eb398192012-10-22 20:16:19246 GPUVideoMemoryUsageStats video_memory_usage_stats;
[email protected]59383c782013-04-17 16:43:27247 if (gpu_channel_manager_)
[email protected]fb246af2012-08-18 03:11:41248 gpu_channel_manager_->gpu_memory_manager()->GetVideoMemoryUsageStats(
[email protected]879c7dfd2012-12-19 21:44:37249 &video_memory_usage_stats);
[email protected]fb246af2012-08-18 03:11:41250 Send(new GpuHostMsg_VideoMemoryUsageStats(video_memory_usage_stats));
251}
252
[email protected]184e3f3802011-05-04 20:48:52253void GpuChildThread::OnClean() {
anujk.sharma98e81a12014-11-14 04:54:21254 DVLOG(1) << "GPU: Removing all contexts";
[email protected]59383c782013-04-17 16:43:27255 if (gpu_channel_manager_)
[email protected]184e3f3802011-05-04 20:48:52256 gpu_channel_manager_->LoseAllContexts();
257}
258
[email protected]7a31f7c2011-03-21 23:22:04259void GpuChildThread::OnCrash() {
anujk.sharma98e81a12014-11-14 04:54:21260 DVLOG(1) << "GPU: Simulating GPU crash";
[email protected]43ed6282010-09-15 20:07:19261 // Good bye, cruel world.
262 volatile int* it_s_the_end_of_the_world_as_we_know_it = NULL;
263 *it_s_the_end_of_the_world_as_we_know_it = 0xdead;
264}
[email protected]259750d2010-09-24 06:14:00265
[email protected]7a31f7c2011-03-21 23:22:04266void GpuChildThread::OnHang() {
anujk.sharma98e81a12014-11-14 04:54:21267 DVLOG(1) << "GPU: Simulating GPU hang";
[email protected]981c1c52010-12-01 20:09:24268 for (;;) {
269 // Do not sleep here. The GPU watchdog timer tracks the amount of user
270 // time this thread is using and it doesn't use much while calling Sleep.
271 }
[email protected]259750d2010-09-24 06:14:00272}
[email protected]41579ae2010-11-15 22:31:26273
[email protected]31583a9d2012-11-30 00:37:17274void GpuChildThread::OnDisableWatchdog() {
anujk.sharma98e81a12014-11-14 04:54:21275 DVLOG(1) << "GPU: Disabling watchdog thread";
[email protected]fc72bb12013-06-02 21:13:46276 if (watchdog_thread_.get()) {
[email protected]31583a9d2012-11-30 00:37:17277 // Disarm the watchdog before shutting down the message loop. This prevents
278 // the future posting of tasks to the message loop.
279 if (watchdog_thread_->message_loop())
280 watchdog_thread_->PostAcknowledge();
281 // Prevent rearming.
282 watchdog_thread_->Stop();
283 }
284}
285
ccameron17d51092014-10-24 22:17:07286void GpuChildThread::OnGpuSwitched() {
anujk.sharma98e81a12014-11-14 04:54:21287 DVLOG(1) << "GPU: GPU has switched";
ccameron17d51092014-10-24 22:17:07288 // Notify observers in the GPU process.
289 ui::GpuSwitchingManager::GetInstance()->NotifyGpuSwitched();
290}
291
[email protected]eb398192012-10-22 20:16:19292} // namespace content
293