blob: af4027bebc2c50abf40af6c9aecef8f1cd4fbca7 [file] [log] [blame]
[email protected]2e3d9e42012-02-14 03:23:381// 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
avi66a07722015-12-25 23:38:125#include <stddef.h>
[email protected]e09cee42010-11-09 01:50:086#include <stdlib.h>
7
mostynb6682b1c42016-04-19 10:17:308#include <memory>
dchengf26eed32016-01-13 10:58:149#include <utility>
10
[email protected]ec4bda62013-06-14 15:51:0311#include "base/lazy_instance.h"
[email protected]e55f5642013-07-18 00:22:5412#include "base/message_loop/message_loop.h"
[email protected]2f2fd9e2013-12-05 03:36:3013#include "base/metrics/histogram.h"
jmadill29fda8632015-03-18 22:45:2214#include "base/metrics/statistics_recorder.h"
[email protected]2436a6b2012-04-13 21:08:5115#include "base/rand_util.h"
fdoraye716a902016-07-05 16:05:4916#include "base/run_loop.h"
[email protected]d0ea4782013-06-11 04:58:2417#include "base/strings/string_number_conversions.h"
18#include "base/strings/stringprintf.h"
glider6b8d75a42015-02-20 11:44:5019#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
[email protected]ce072a72010-12-31 20:02:1620#include "base/threading/platform_thread.h"
primiano50b7444c2015-01-28 04:17:0021#include "base/trace_event/trace_event.h"
[email protected]c0fc0942010-01-13 00:55:3722#include "build/build_config.h"
[email protected]10208ea2013-06-06 20:08:0323#include "content/child/child_process.h"
[email protected]91a2aea2013-07-08 23:14:3924#include "content/common/content_constants_internal.h"
fsamuel115b5ed42016-03-22 19:41:5825#include "content/common/gpu_host_messages.h"
[email protected]5c9cddd2013-12-13 07:03:2926#include "content/common/sandbox_linux/sandbox_linux.h"
[email protected]7a31f7c2011-03-21 23:22:0427#include "content/gpu/gpu_child_thread.h"
[email protected]623c0bd2011-03-12 01:00:4128#include "content/gpu/gpu_process.h"
[email protected]c9e2cbbb2012-05-12 21:17:2729#include "content/public/common/content_client.h"
30#include "content/public/common/content_switches.h"
31#include "content/public/common/main_function_params.h"
[email protected]40c19e722013-11-05 23:51:2432#include "gpu/command_buffer/service/gpu_switches.h"
[email protected]d7b5cc72013-05-23 20:05:0033#include "gpu/config/gpu_info_collector.h"
tfarina15525c42015-04-28 19:04:1634#include "gpu/config/gpu_switches.h"
[email protected]40c19e722013-11-05 23:51:2435#include "gpu/config/gpu_util.h"
fsamuelc2774222016-03-24 00:27:1236#include "gpu/ipc/common/gpu_memory_buffer_support.h"
markdittmerd88b8352016-04-08 15:28:4537#include "gpu/ipc/service/gpu_config.h"
38#include "gpu/ipc/service/gpu_memory_buffer_factory.h"
sadrul2fb7e152016-08-30 05:21:4539#include "gpu/ipc/service/gpu_watchdog_thread.h"
[email protected]c0939182014-05-24 00:09:1940#include "ui/events/platform/platform_event_source.h"
martina.kollarovaa34211d2015-06-25 11:49:0741#include "ui/gl/gl_context.h"
[email protected]db6101db2012-10-25 15:20:0842#include "ui/gl/gl_implementation.h"
[email protected]c9e2cbbb2012-05-12 21:17:2743#include "ui/gl/gl_surface.h"
44#include "ui/gl/gl_switches.h"
[email protected]1bb06b02012-09-23 19:37:2445#include "ui/gl/gpu_switching_manager.h"
kylechar5b9dec12016-05-16 15:40:5746#include "ui/gl/init/gl_factory.h"
[email protected]c0fc0942010-01-13 00:55:3747
avi66a07722015-12-25 23:38:1248#if defined(OS_WIN)
avi66a07722015-12-25 23:38:1249#include <windows.h>
fdoraye716a902016-07-05 16:05:4950#include <dwmapi.h>
avi66a07722015-12-25 23:38:1251#endif
52
primianob3fb6412015-10-14 16:03:5153#if defined(OS_ANDROID)
54#include "base/trace_event/memory_dump_manager.h"
primianoccb26c62016-06-01 21:50:0255#include "components/tracing/common/graphics_memory_dump_provider_android.h"
primianob3fb6412015-10-14 16:03:5156#endif
57
[email protected]d7de57872011-12-06 23:32:4358#if defined(OS_WIN)
[email protected]5f7e4512012-10-01 20:51:3759#include "base/win/scoped_com_initializer.h"
kylechar5b9dec12016-05-16 15:40:5760#include "base/win/windows_version.h"
markdittmer6e70beb82016-05-02 05:40:4761#include "media/gpu/dxva_video_decode_accelerator_win.h"
emircanc253d05a2016-07-22 23:21:1162#include "media/gpu/media_foundation_video_encode_accelerator_win.h"
[email protected]181491782012-07-18 00:59:1563#include "sandbox/win/src/sandbox.h"
[email protected]802a13a02010-12-02 01:48:3764#endif
65
[email protected]02ec37a2010-09-20 22:32:1666#if defined(USE_X11)
kylecharfe6518f2016-04-29 13:56:5067#include "ui/base/x/x11_util.h" // nogncheck
kylechar4abed71f2016-04-06 14:46:4268#include "ui/gfx/x/x11_switches.h" // nogncheck
[email protected]02ec37a2010-09-20 22:32:1669#endif
70
[email protected]2436a6b2012-04-13 21:08:5171#if defined(OS_LINUX)
72#include "content/public/common/sandbox_init.h"
73#endif
74
[email protected]826aab02014-05-14 02:58:5975#if defined(OS_MACOSX)
76#include "base/message_loop/message_pump_mac.h"
[email protected]6abc8082014-07-11 10:35:4677#include "content/common/sandbox_mac.h"
[email protected]826aab02014-05-14 02:58:5978#endif
79
hshi95837052015-05-12 15:39:5180#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
markdittmer6e70beb82016-05-02 05:40:4781#include "media/gpu/vaapi_wrapper.h"
hshi95837052015-05-12 15:39:5182#endif
83
gliderddea13b2015-02-13 18:01:3084#if defined(SANITIZER_COVERAGE)
85#include <sanitizer/common_interface_defs.h>
hans832e5292015-03-05 04:02:1186#include <sanitizer/coverage_interface.h>
[email protected]655abd522014-06-02 15:23:4387#endif
88
[email protected]eb398192012-10-22 20:16:1989namespace content {
[email protected]ec4bda62013-06-14 15:51:0390
[email protected]6ec3a572012-08-17 02:09:5191namespace {
[email protected]ec4bda62013-06-14 15:51:0392
[email protected]b80059f2014-06-12 11:00:4693void GetGpuInfoFromCommandLine(gpu::GPUInfo& gpu_info,
avi83883c82014-12-23 00:08:4994 const base::CommandLine& command_line);
Sadrul Habib Chowdhuryc0a4a9b92016-08-29 21:43:2495void WarmUpSandbox();
[email protected]b80059f2014-06-12 11:00:4696
97#if !defined(OS_MACOSX)
98bool CollectGraphicsInfo(gpu::GPUInfo& gpu_info);
99#endif
100
[email protected]663c4b32013-04-18 05:52:54101#if defined(OS_LINUX)
[email protected]b80059f2014-06-12 11:00:46102#if !defined(OS_CHROMEOS)
103bool CanAccessNvidiaDeviceFile();
104#endif
sadrul2fb7e152016-08-30 05:21:45105bool StartSandboxLinux(const gpu::GPUInfo&, gpu::GpuWatchdogThread*);
[email protected]663c4b32013-04-18 05:52:54106#elif defined(OS_WIN)
107bool StartSandboxWindows(const sandbox::SandboxInterfaceInfo*);
108#endif
[email protected]ec4bda62013-06-14 15:51:03109
110base::LazyInstance<GpuChildThread::DeferredMessages> deferred_messages =
111 LAZY_INSTANCE_INITIALIZER;
112
113bool GpuProcessLogMessageHandler(int severity,
114 const char* file, int line,
115 size_t message_start,
116 const std::string& str) {
117 std::string header = str.substr(0, message_start);
118 std::string message = str.substr(message_start);
fsamuela660ce02016-02-25 03:56:16119 deferred_messages.Get().push(
120 new GpuHostMsg_OnLogMessage(severity, header, message));
[email protected]ec4bda62013-06-14 15:51:03121 return false;
[email protected]6ec3a572012-08-17 02:09:51122}
123
[email protected]ec4bda62013-06-14 15:51:03124} // namespace anonymous
125
[email protected]c0fc0942010-01-13 00:55:37126// Main function for starting the Gpu process.
[email protected]eb398192012-10-22 20:16:19127int GpuMain(const MainFunctionParams& parameters) {
[email protected]d13f35d2012-05-18 02:28:15128 TRACE_EVENT0("gpu", "GpuMain");
ssidb2e3ece2015-02-09 16:02:20129 base::trace_event::TraceLog::GetInstance()->SetProcessName("GPU Process");
130 base::trace_event::TraceLog::GetInstance()->SetProcessSortIndex(
[email protected]91a2aea2013-07-08 23:14:39131 kTraceEventGpuProcessSortIndex);
[email protected]d13f35d2012-05-18 02:28:15132
avi83883c82014-12-23 00:08:49133 const base::CommandLine& command_line = parameters.command_line;
[email protected]6b889fb2010-03-23 20:09:49134 if (command_line.HasSwitch(switches::kGpuStartupDialog)) {
[email protected]75fcc272011-03-08 20:50:48135 ChildProcess::WaitForDebugger("Gpu");
[email protected]6b889fb2010-03-23 20:09:49136 }
137
[email protected]ca23992b02013-06-13 17:25:19138 base::Time start_time = base::Time::Now();
139
[email protected]23f46562011-09-07 01:42:39140#if defined(OS_WIN)
[email protected]52819472013-11-24 22:49:55141 // Prevent Windows from displaying a modal dialog on failures like not being
142 // able to load a DLL.
143 SetErrorMode(
144 SEM_FAILCRITICALERRORS |
145 SEM_NOGPFAULTERRORBOX |
146 SEM_NOOPENFILEERRORBOX);
[email protected]23f46562011-09-07 01:42:39147#elif defined(USE_X11)
[email protected]52819472013-11-24 22:49:55148 ui::SetDefaultX11ErrorHandlers();
j.isorce5ade8482015-11-23 16:15:12149
150#if !defined(OS_CHROMEOS)
151 DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
152 switches::kWindowDepth));
j.isorcea1e42242016-05-19 05:11:28153 DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
154 switches::kX11VisualID));
j.isorce5ade8482015-11-23 16:15:12155#endif
156
[email protected]23f46562011-09-07 01:42:39157#endif
[email protected]ec4bda62013-06-14 15:51:03158
[email protected]52819472013-11-24 22:49:55159 logging::SetLogMessageHandler(GpuProcessLogMessageHandler);
[email protected]23f46562011-09-07 01:42:39160
[email protected]40c19e722013-11-05 23:51:24161 if (command_line.HasSwitch(switches::kSupportsDualGpus)) {
162 std::string types = command_line.GetSwitchValueASCII(
163 switches::kGpuDriverBugWorkarounds);
164 std::set<int> workarounds;
165 gpu::StringToFeatureSet(types, &workarounds);
166 if (workarounds.count(gpu::FORCE_DISCRETE_GPU) == 1)
[email protected]a2221e82012-10-08 22:33:14167 ui::GpuSwitchingManager::GetInstance()->ForceUseOfDiscreteGpu();
[email protected]40c19e722013-11-05 23:51:24168 else if (workarounds.count(gpu::FORCE_INTEGRATED_GPU) == 1)
[email protected]a2221e82012-10-08 22:33:14169 ui::GpuSwitchingManager::GetInstance()->ForceUseOfIntegratedGpu();
[email protected]1bb06b02012-09-23 19:37:24170 }
171
[email protected]0b2cec62011-07-22 18:13:28172 // Initialization of the OpenGL bindings may fail, in which case we
173 // will need to tear down this process. However, we can not do so
174 // safely until the IPC channel is set up, because the detection of
175 // early return of a child process is implemented using an IPC
176 // channel error. If the IPC channel is not fully set up between the
177 // browser and GPU process, and the GPU process crashes or exits
178 // early, the browser process will never detect it. For this reason
179 // we defer tearing down the GPU process until receiving the
180 // GpuMsg_Initialize message from the browser.
181 bool dead_on_arrival = false;
182
[email protected]db6101db2012-10-25 15:20:08183#if defined(OS_WIN)
geofflang019d4f32015-04-27 21:39:39184 // Use a UI message loop because ANGLE and the desktop GL platform can
185 // create child windows to render to.
stanisc100d03d2016-05-26 18:39:51186 base::MessagePumpForGpu::InitFactory();
jbaumanca6bfb52015-07-01 21:17:52187 base::MessageLoop main_message_loop(base::MessageLoop::TYPE_UI);
[email protected]c0939182014-05-24 00:09:19188#elif defined(OS_LINUX) && defined(USE_X11)
189 // We need a UI loop so that we can grab the Expose events. See GLSurfaceGLX
190 // and https://crbug.com/326995.
191 base::MessageLoop main_message_loop(base::MessageLoop::TYPE_UI);
dcheng6003e0b2016-04-09 18:42:34192 std::unique_ptr<ui::PlatformEventSource> event_source =
[email protected]c0939182014-05-24 00:09:19193 ui::PlatformEventSource::CreateDefault();
[email protected]db6101db2012-10-25 15:20:08194#elif defined(OS_LINUX)
[email protected]826aab02014-05-14 02:58:59195 base::MessageLoop main_message_loop(base::MessageLoop::TYPE_DEFAULT);
196#elif defined(OS_MACOSX)
197 // This is necessary for CoreAnimation layers hosted in the GPU process to be
198 // drawn. See http://crbug.com/312462.
dcheng6003e0b2016-04-09 18:42:34199 std::unique_ptr<base::MessagePump> pump(new base::MessagePumpCFRunLoop());
dchengf26eed32016-01-13 10:58:14200 base::MessageLoop main_message_loop(std::move(pump));
[email protected]826aab02014-05-14 02:58:59201#else
202 base::MessageLoop main_message_loop(base::MessageLoop::TYPE_IO);
[email protected]db6101db2012-10-25 15:20:08203#endif
204
[email protected]db6101db2012-10-25 15:20:08205 base::PlatformThread::SetName("CrGpuMain");
206
207 // In addition to disabling the watchdog if the command line switch is
208 // present, disable the watchdog on valgrind because the code is expected
209 // to run slowly in that case.
210 bool enable_watchdog =
[email protected]ca23992b02013-06-13 17:25:19211 !command_line.HasSwitch(switches::kDisableGpuWatchdog) &&
[email protected]db6101db2012-10-25 15:20:08212 !RunningOnValgrind();
213
214 // Disable the watchdog in debug builds because they tend to only be run by
215 // developers who will not appreciate the watchdog killing the GPU process.
216#ifndef NDEBUG
217 enable_watchdog = false;
218#endif
219
[email protected]42719602012-11-08 02:51:12220 bool delayed_watchdog_enable = false;
221
222#if defined(OS_CHROMEOS)
223 // Don't start watchdog immediately, to allow developers to switch to VT2 on
224 // startup.
225 delayed_watchdog_enable = true;
226#endif
227
sadrul2fb7e152016-08-30 05:21:45228 scoped_refptr<gpu::GpuWatchdogThread> watchdog_thread;
[email protected]db6101db2012-10-25 15:20:08229
230 // Start the GPU watchdog only after anything that is expected to be time
231 // consuming has completed, otherwise the process is liable to be aborted.
sadrul2fb7e152016-08-30 05:21:45232 if (enable_watchdog && !delayed_watchdog_enable)
233 watchdog_thread = gpu::GpuWatchdogThread::Create();
[email protected]db6101db2012-10-25 15:20:08234
jmadill29fda8632015-03-18 22:45:22235 // Initializes StatisticsRecorder which tracks UMA histograms.
236 base::StatisticsRecorder::Initialize();
237
[email protected]d7b5cc72013-05-23 20:05:00238 gpu::GPUInfo gpu_info;
[email protected]085170ca2012-05-17 20:27:28239 // Get vendor_id, device_id, driver_version from browser process through
240 // commandline switches.
[email protected]b80059f2014-06-12 11:00:46241 GetGpuInfoFromCommandLine(gpu_info, command_line);
bajonese3677b642015-07-25 00:41:56242 gpu_info.in_process_gpu = false;
[email protected]f0918242012-02-18 00:30:50243
hshi95837052015-05-12 15:39:51244#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
markdittmer6e70beb82016-05-02 05:40:47245 media::VaapiWrapper::PreSandboxInitialization();
hshi95837052015-05-12 15:39:51246#endif
247
revemane7acf842016-02-05 08:24:32248#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
249 // Set thread priority before sandbox initialization.
250 base::PlatformThread::SetCurrentThreadPriority(base::ThreadPriority::DISPLAY);
251#endif
252
[email protected]663c4b32013-04-18 05:52:54253 // Warm up resources that don't need access to GPUInfo.
Sadrul Habib Chowdhuryc0a4a9b92016-08-29 21:43:24254 WarmUpSandbox();
255
[email protected]663c4b32013-04-18 05:52:54256#if defined(OS_LINUX)
Sadrul Habib Chowdhuryc0a4a9b92016-08-29 21:43:24257 bool initialized_sandbox = false;
258 // On Chrome OS ARM Mali, GPU driver userspace creates threads when
259 // initializing a GL context, so start the sandbox early.
260 if (command_line.HasSwitch(switches::kGpuSandboxStartEarly)) {
261 gpu_info.sandboxed = StartSandboxLinux(gpu_info, watchdog_thread.get());
262 initialized_sandbox = true;
263 }
[email protected]663c4b32013-04-18 05:52:54264#endif // defined(OS_LINUX)
265
Sadrul Habib Chowdhuryc0a4a9b92016-08-29 21:43:24266 base::TimeTicks before_initialize_one_off = base::TimeTicks::Now();
[email protected]2f2fd9e2013-12-05 03:36:30267
Sadrul Habib Chowdhuryc0a4a9b92016-08-29 21:43:24268 // Determine if we need to initialize GL here or it has already been done.
269 bool gl_already_initialized = false;
[email protected]af7c5d92014-02-03 19:53:15270#if defined(OS_MACOSX)
Sadrul Habib Chowdhuryc0a4a9b92016-08-29 21:43:24271 if (!command_line.HasSwitch(switches::kNoSandbox)) {
272 // On Mac, if the sandbox is enabled, then gl::init::InitializeGLOneOff()
273 // is called from the sandbox warmup code before getting here.
274 gl_already_initialized = true;
275 }
[email protected]af7c5d92014-02-03 19:53:15276#endif
Sadrul Habib Chowdhuryc0a4a9b92016-08-29 21:43:24277 if (command_line.HasSwitch(switches::kInProcessGPU)) {
278 // With in-process GPU, gl::init::InitializeGLOneOff() is called from
279 // GpuChildThread before getting here.
280 gl_already_initialized = true;
281 }
[email protected]af7c5d92014-02-03 19:53:15282
Sadrul Habib Chowdhuryc0a4a9b92016-08-29 21:43:24283 // Load and initialize the GL implementation and locate the GL entry points.
284 bool gl_initialized =
285 gl_already_initialized
286 ? gl::GetGLImplementation() != gl::kGLImplementationNone
287 : gl::init::InitializeGLOneOff();
288 if (gl_initialized) {
289 // We need to collect GL strings (VENDOR, RENDERER) for blacklisting
290 // purposes. However, on Mac we don't actually use them. As documented in
291 // crbug.com/222934, due to some driver issues, glGetString could take
292 // multiple seconds to finish, which in turn cause the GPU process to
293 // crash.
294 // By skipping the following code on Mac, we don't really lose anything,
295 // because the basic GPU information is passed down from browser process
296 // and we already registered them through SetGpuInfo() above.
297 base::TimeTicks before_collect_context_graphics_info =
298 base::TimeTicks::Now();
[email protected]e9931a42013-04-11 00:48:41299#if !defined(OS_MACOSX)
Sadrul Habib Chowdhuryc0a4a9b92016-08-29 21:43:24300 if (!CollectGraphicsInfo(gpu_info))
[email protected]ca23992b02013-06-13 17:25:19301 dead_on_arrival = true;
Sadrul Habib Chowdhuryc0a4a9b92016-08-29 21:43:24302
303 // Recompute gpu driver bug workarounds.
304 // This is necessary on systems where vendor_id/device_id aren't available
305 // (Chrome OS, Android) or where workarounds may be dependent on GL_VENDOR
306 // and GL_RENDERER strings which are lazily computed (Linux).
307 if (!command_line.HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) {
308 // TODO: this can not affect disabled extensions, since they're already
309 // initialized in the bindings. This should be moved before bindings
310 // initialization. However, populating GPUInfo fully works only on
311 // Android. Other platforms would need the bindings to query GL strings.
312 gpu::ApplyGpuDriverBugWorkarounds(
313 gpu_info, const_cast<base::CommandLine*>(&command_line));
[email protected]ca23992b02013-06-13 17:25:19314 }
Sadrul Habib Chowdhuryc0a4a9b92016-08-29 21:43:24315#endif // !defined(OS_MACOSX)
[email protected]4a2a4d22011-07-25 23:20:34316
Sadrul Habib Chowdhuryc0a4a9b92016-08-29 21:43:24317#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
318 if (gpu_info.gpu.vendor_id == 0x10de && // NVIDIA
319 gpu_info.driver_vendor == "NVIDIA" && !CanAccessNvidiaDeviceFile())
320 dead_on_arrival = true;
321#endif // defined(OS_LINUX) && !defined(OS_CHROMEOS)
[email protected]2f2fd9e2013-12-05 03:36:30322
Sadrul Habib Chowdhuryc0a4a9b92016-08-29 21:43:24323 base::TimeDelta collect_context_time =
324 base::TimeTicks::Now() - before_collect_context_graphics_info;
325 UMA_HISTOGRAM_TIMES("GPU.CollectContextGraphicsInfo", collect_context_time);
326 } else { // gl_initialized
327 VLOG(1) << "gl::init::InitializeGLOneOff failed";
[email protected]ec4bda62013-06-14 15:51:03328 dead_on_arrival = true;
[email protected]ca23992b02013-06-13 17:25:19329 }
[email protected]0b2cec62011-07-22 18:13:28330
Sadrul Habib Chowdhuryc0a4a9b92016-08-29 21:43:24331 base::TimeDelta initialize_one_off_time =
332 base::TimeTicks::Now() - before_initialize_one_off;
333 UMA_HISTOGRAM_MEDIUM_TIMES("GPU.InitializeOneOffMediumTime",
334 initialize_one_off_time);
sadrul2fb7e152016-08-30 05:21:45335 if (enable_watchdog && delayed_watchdog_enable)
336 watchdog_thread = gpu::GpuWatchdogThread::Create();
Sadrul Habib Chowdhuryc0a4a9b92016-08-29 21:43:24337
338 // OSMesa is expected to run very slowly, so disable the watchdog in that
339 // case.
340 if (enable_watchdog &&
341 gl::GetGLImplementation() == gl::kGLImplementationOSMesaGL) {
342 watchdog_thread->Stop();
343 watchdog_thread = NULL;
344 }
345
346#if defined(OS_LINUX)
347 if (!initialized_sandbox)
348 gpu_info.sandboxed = StartSandboxLinux(gpu_info, watchdog_thread.get());
349#elif defined(OS_WIN)
350 gpu_info.sandboxed = StartSandboxWindows(parameters.sandbox_info);
351#elif defined(OS_MACOSX)
352 gpu_info.sandboxed = Sandbox::SandboxIsCurrentlyActive();
353#endif
354
[email protected]ec4bda62013-06-14 15:51:03355 logging::SetLogMessageHandler(NULL);
356
dcheng6003e0b2016-04-09 18:42:34357 std::unique_ptr<gpu::GpuMemoryBufferFactory> gpu_memory_buffer_factory;
fsamuelc2774222016-03-24 00:27:12358 if (gpu::GetNativeGpuMemoryBufferType() != gfx::EMPTY_BUFFER)
markdittmerd88b8352016-04-08 15:28:45359 gpu_memory_buffer_factory = gpu::GpuMemoryBufferFactory::CreateNativeType();
revemanfb8c8e102015-10-07 20:26:32360
reveman7caf8cf2016-02-16 02:39:05361 base::ThreadPriority io_thread_priority = base::ThreadPriority::NORMAL;
362#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
363 io_thread_priority = base::ThreadPriority::DISPLAY;
364#endif
365
366 GpuProcess gpu_process(io_thread_priority);
[email protected]8fe0ec522011-03-03 00:31:33367
reveman611d024f2015-06-25 22:42:40368 GpuChildThread* child_thread = new GpuChildThread(
369 watchdog_thread.get(), dead_on_arrival, gpu_info, deferred_messages.Get(),
boliu1384d6d2016-04-22 06:38:50370 gpu_memory_buffer_factory.get());
[email protected]ec4bda62013-06-14 15:51:03371 while (!deferred_messages.Get().empty())
372 deferred_messages.Get().pop();
[email protected]8fe0ec522011-03-03 00:31:33373
[email protected]7a31f7c2011-03-21 23:22:04374 child_thread->Init(start_time);
[email protected]995a7f12011-02-11 23:07:17375
[email protected]7a31f7c2011-03-21 23:22:04376 gpu_process.set_main_thread(child_thread);
[email protected]983c33d2010-11-16 22:38:44377
dcheng56ddc2f2014-08-26 23:01:40378 if (watchdog_thread.get())
[email protected]21e24902013-08-06 20:23:48379 watchdog_thread->AddPowerObserver();
380
primianob3fb6412015-10-14 16:03:51381#if defined(OS_ANDROID)
382 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
primiano186d6bfe2015-10-30 13:21:40383 tracing::GraphicsMemoryDumpProvider::GetInstance(), "AndroidGraphics",
384 nullptr);
primianob3fb6412015-10-14 16:03:51385#endif
386
[email protected]d13f35d2012-05-18 02:28:15387 {
388 TRACE_EVENT0("gpu", "Run Message Loop");
fdoraye716a902016-07-05 16:05:49389 base::RunLoop().Run();
[email protected]d13f35d2012-05-18 02:28:15390 }
[email protected]c0fc0942010-01-13 00:55:37391
[email protected]7a31f7c2011-03-21 23:22:04392 child_thread->StopWatchdog();
[email protected]e09cee42010-11-09 01:50:08393
[email protected]c0fc0942010-01-13 00:55:37394 return 0;
395}
[email protected]6ec3a572012-08-17 02:09:51396
397namespace {
398
[email protected]b80059f2014-06-12 11:00:46399void GetGpuInfoFromCommandLine(gpu::GPUInfo& gpu_info,
avi83883c82014-12-23 00:08:49400 const base::CommandLine& command_line) {
[email protected]b80059f2014-06-12 11:00:46401 DCHECK(command_line.HasSwitch(switches::kGpuVendorID) &&
402 command_line.HasSwitch(switches::kGpuDeviceID) &&
403 command_line.HasSwitch(switches::kGpuDriverVersion));
404 bool success = base::HexStringToUInt(
405 command_line.GetSwitchValueASCII(switches::kGpuVendorID),
406 &gpu_info.gpu.vendor_id);
407 DCHECK(success);
408 success = base::HexStringToUInt(
409 command_line.GetSwitchValueASCII(switches::kGpuDeviceID),
410 &gpu_info.gpu.device_id);
411 DCHECK(success);
412 gpu_info.driver_vendor =
413 command_line.GetSwitchValueASCII(switches::kGpuDriverVendor);
414 gpu_info.driver_version =
415 command_line.GetSwitchValueASCII(switches::kGpuDriverVersion);
j.isorcefecf94b2016-04-28 05:52:15416 gpu_info.driver_date =
417 command_line.GetSwitchValueASCII(switches::kGpuDriverDate);
j.isorce74cae7402016-04-25 20:00:58418 gpu::ParseSecondaryGpuDevicesFromCommandLine(command_line, &gpu_info);
419
420 // Set active gpu device.
421 if (command_line.HasSwitch(switches::kGpuActiveVendorID) &&
422 command_line.HasSwitch(switches::kGpuActiveDeviceID)) {
423 uint32_t active_vendor_id = 0;
424 uint32_t active_device_id = 0;
425 success = base::HexStringToUInt(
426 command_line.GetSwitchValueASCII(switches::kGpuActiveVendorID),
427 &active_vendor_id);
428 DCHECK(success);
429 success = base::HexStringToUInt(
430 command_line.GetSwitchValueASCII(switches::kGpuActiveDeviceID),
431 &active_device_id);
432 DCHECK(success);
433 if (gpu_info.gpu.vendor_id == active_vendor_id &&
434 gpu_info.gpu.device_id == active_device_id) {
435 gpu_info.gpu.active = true;
436 } else {
437 for (size_t i = 0; i < gpu_info.secondary_gpus.size(); ++i) {
438 if (gpu_info.secondary_gpus[i].vendor_id == active_vendor_id &&
439 gpu_info.secondary_gpus[i].device_id == active_device_id) {
440 gpu_info.secondary_gpus[i].active = true;
441 break;
442 }
443 }
444 }
445 }
446
[email protected]b80059f2014-06-12 11:00:46447 GetContentClient()->SetGpuInfo(gpu_info);
448}
449
Sadrul Habib Chowdhuryc0a4a9b92016-08-29 21:43:24450void WarmUpSandbox() {
[email protected]b80059f2014-06-12 11:00:46451 {
452 TRACE_EVENT0("gpu", "Warm up rand");
453 // Warm up the random subsystem, which needs to be done pre-sandbox on all
454 // platforms.
455 (void) base::RandUint64();
456 }
anantab03aa1792015-11-06 01:21:32457
458#if defined(OS_WIN)
markdittmer6e70beb82016-05-02 05:40:47459 media::DXVAVideoDecodeAccelerator::PreSandboxInitialization();
emircanc253d05a2016-07-22 23:21:11460 media::MediaFoundationVideoEncodeAccelerator::PreSandboxInitialization();
anantab03aa1792015-11-06 01:21:32461#endif
[email protected]b80059f2014-06-12 11:00:46462}
463
464#if !defined(OS_MACOSX)
465bool CollectGraphicsInfo(gpu::GPUInfo& gpu_info) {
fdorayf30bf3a2015-10-28 21:47:00466 TRACE_EVENT0("gpu,startup", "Collect Graphics Info");
467
[email protected]b80059f2014-06-12 11:00:46468 bool res = true;
469 gpu::CollectInfoResult result = gpu::CollectContextGraphicsInfo(&gpu_info);
470 switch (result) {
471 case gpu::kCollectInfoFatalFailure:
472 LOG(ERROR) << "gpu::CollectGraphicsInfo failed (fatal).";
473 res = false;
474 break;
475 case gpu::kCollectInfoNonFatalFailure:
anujk.sharma98e81a12014-11-14 04:54:21476 DVLOG(1) << "gpu::CollectGraphicsInfo failed (non-fatal).";
[email protected]b80059f2014-06-12 11:00:46477 break;
zmo84eae5e2014-09-05 01:36:23478 case gpu::kCollectInfoNone:
479 NOTREACHED();
480 break;
[email protected]b80059f2014-06-12 11:00:46481 case gpu::kCollectInfoSuccess:
482 break;
483 }
484 GetContentClient()->SetGpuInfo(gpu_info);
485 return res;
486}
487#endif
488
[email protected]59a7ae4e2012-10-01 23:54:44489#if defined(OS_LINUX)
[email protected]b80059f2014-06-12 11:00:46490#if !defined(OS_CHROMEOS)
491bool CanAccessNvidiaDeviceFile() {
492 bool res = true;
493 base::ThreadRestrictions::AssertIOAllowed();
494 if (access("/dev/nvidiactl", R_OK) != 0) {
anujk.sharma98e81a12014-11-14 04:54:21495 DVLOG(1) << "NVIDIA device file /dev/nvidiactl access denied";
[email protected]b80059f2014-06-12 11:00:46496 res = false;
497 }
498 return res;
499}
500#endif
501
[email protected]d7b5cc72013-05-23 20:05:00502bool StartSandboxLinux(const gpu::GPUInfo& gpu_info,
sadrul2fb7e152016-08-30 05:21:45503 gpu::GpuWatchdogThread* watchdog_thread) {
fdorayf30bf3a2015-10-28 21:47:00504 TRACE_EVENT0("gpu,startup", "Initialize sandbox");
[email protected]663c4b32013-04-18 05:52:54505
506 bool res = false;
507
[email protected]f330b762014-02-08 04:52:46508 if (watchdog_thread) {
509 // LinuxSandbox needs to be able to ensure that the thread
510 // has really been stopped.
511 LinuxSandbox::StopThread(watchdog_thread);
512 }
[email protected]655abd522014-06-02 15:23:43513
gliderddea13b2015-02-13 18:01:30514#if defined(SANITIZER_COVERAGE)
[email protected]356b52022014-06-03 21:57:38515 const std::string sancov_file_name =
516 "gpu." + base::Uint64ToString(base::RandUint64());
[email protected]655abd522014-06-02 15:23:43517 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance();
518 linux_sandbox->sanitizer_args()->coverage_sandboxed = 1;
[email protected]356b52022014-06-03 21:57:38519 linux_sandbox->sanitizer_args()->coverage_fd =
520 __sanitizer_maybe_open_cov_file(sancov_file_name.c_str());
[email protected]655abd522014-06-02 15:23:43521 linux_sandbox->sanitizer_args()->coverage_max_block_size = 0;
522#endif
523
[email protected]663c4b32013-04-18 05:52:54524 // LinuxSandbox::InitializeSandbox() must always be called
525 // with only one thread.
526 res = LinuxSandbox::InitializeSandbox();
[email protected]f330b762014-02-08 04:52:46527 if (watchdog_thread) {
tonyg3f2962f2014-09-16 02:14:43528 base::Thread::Options options;
529 options.timer_slack = base::TIMER_SLACK_MAXIMUM;
530 watchdog_thread->StartWithOptions(options);
[email protected]f330b762014-02-08 04:52:46531 }
[email protected]663c4b32013-04-18 05:52:54532
533 return res;
534}
535#endif // defined(OS_LINUX)
536
537#if defined(OS_WIN)
538bool StartSandboxWindows(const sandbox::SandboxInterfaceInfo* sandbox_info) {
fdorayf30bf3a2015-10-28 21:47:00539 TRACE_EVENT0("gpu,startup", "Lower token");
[email protected]663c4b32013-04-18 05:52:54540
541 // For Windows, if the target_services interface is not zero, the process
542 // is sandboxed and we must call LowerToken() before rendering untrusted
543 // content.
544 sandbox::TargetServices* target_services = sandbox_info->target_services;
545 if (target_services) {
546 target_services->LowerToken();
547 return true;
548 }
549
550 return false;
551}
552#endif // defined(OS_WIN)
553
[email protected]6ec3a572012-08-17 02:09:51554} // namespace.
555
[email protected]eb398192012-10-22 20:16:19556} // namespace content