Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: content/gpu/gpu_main.cc

Issue 2289553002: gpu: Introduce GpuInit. (Closed)
Patch Set: . Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/gpu/gpu_child_thread.cc ('k') | content/public/common/content_switches.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 <stddef.h> 5 #include <stddef.h>
6 #include <stdlib.h> 6 #include <stdlib.h>
7 7
8 #include <memory> 8 #include <memory>
9 #include <utility> 9 #include <utility>
10 10
11 #include "base/lazy_instance.h"
12 #include "base/message_loop/message_loop.h" 11 #include "base/message_loop/message_loop.h"
13 #include "base/metrics/histogram.h"
14 #include "base/metrics/statistics_recorder.h"
15 #include "base/rand_util.h" 12 #include "base/rand_util.h"
16 #include "base/run_loop.h" 13 #include "base/run_loop.h"
17 #include "base/strings/string_number_conversions.h" 14 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/stringprintf.h" 15 #include "base/strings/stringprintf.h"
19 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" 16 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
20 #include "base/threading/platform_thread.h" 17 #include "base/threading/platform_thread.h"
21 #include "base/trace_event/trace_event.h" 18 #include "base/trace_event/trace_event.h"
22 #include "build/build_config.h" 19 #include "build/build_config.h"
23 #include "content/child/child_process.h" 20 #include "content/child/child_process.h"
24 #include "content/common/content_constants_internal.h" 21 #include "content/common/content_constants_internal.h"
25 #include "content/common/gpu_host_messages.h"
26 #include "content/common/sandbox_linux/sandbox_linux.h" 22 #include "content/common/sandbox_linux/sandbox_linux.h"
27 #include "content/gpu/gpu_child_thread.h" 23 #include "content/gpu/gpu_child_thread.h"
28 #include "content/gpu/gpu_process.h" 24 #include "content/gpu/gpu_process.h"
29 #include "content/public/common/content_client.h" 25 #include "content/public/common/content_client.h"
30 #include "content/public/common/content_switches.h" 26 #include "content/public/common/content_switches.h"
31 #include "content/public/common/main_function_params.h" 27 #include "content/public/common/main_function_params.h"
32 #include "gpu/command_buffer/service/gpu_switches.h" 28 #include "gpu/command_buffer/service/gpu_switches.h"
33 #include "gpu/config/gpu_info_collector.h" 29 #include "gpu/config/gpu_info_collector.h"
34 #include "gpu/config/gpu_switches.h"
35 #include "gpu/config/gpu_util.h"
36 #include "gpu/ipc/common/gpu_memory_buffer_support.h"
37 #include "gpu/ipc/service/gpu_config.h" 30 #include "gpu/ipc/service/gpu_config.h"
38 #include "gpu/ipc/service/gpu_memory_buffer_factory.h" 31 #include "gpu/ipc/service/gpu_init.h"
32 #include "gpu/ipc/service/gpu_init_delegate.h"
39 #include "gpu/ipc/service/gpu_watchdog_thread.h" 33 #include "gpu/ipc/service/gpu_watchdog_thread.h"
40 #include "ui/events/platform/platform_event_source.h" 34 #include "ui/events/platform/platform_event_source.h"
41 #include "ui/gl/gl_context.h"
42 #include "ui/gl/gl_implementation.h"
43 #include "ui/gl/gl_surface.h"
44 #include "ui/gl/gl_switches.h"
45 #include "ui/gl/gpu_switching_manager.h"
46 #include "ui/gl/init/gl_factory.h"
47 35
48 #if defined(OS_WIN) 36 #if defined(OS_WIN)
49 #include <windows.h> 37 #include <windows.h>
50 #include <dwmapi.h> 38 #include <dwmapi.h>
51 #endif 39 #endif
52 40
53 #if defined(OS_ANDROID) 41 #if defined(OS_ANDROID)
54 #include "base/trace_event/memory_dump_manager.h" 42 #include "base/trace_event/memory_dump_manager.h"
55 #include "components/tracing/common/graphics_memory_dump_provider_android.h" 43 #include "components/tracing/common/graphics_memory_dump_provider_android.h"
56 #endif 44 #endif
57 45
58 #if defined(OS_WIN) 46 #if defined(OS_WIN)
59 #include "base/win/scoped_com_initializer.h" 47 #include "base/win/scoped_com_initializer.h"
60 #include "base/win/windows_version.h" 48 #include "base/win/windows_version.h"
61 #include "media/gpu/dxva_video_decode_accelerator_win.h" 49 #include "media/gpu/dxva_video_decode_accelerator_win.h"
62 #include "media/gpu/media_foundation_video_encode_accelerator_win.h" 50 #include "media/gpu/media_foundation_video_encode_accelerator_win.h"
63 #include "sandbox/win/src/sandbox.h" 51 #include "sandbox/win/src/sandbox.h"
64 #endif 52 #endif
65 53
66 #if defined(USE_X11) 54 #if defined(USE_X11)
67 #include "ui/base/x/x11_util.h" // nogncheck
68 #include "ui/gfx/x/x11_switches.h" // nogncheck 55 #include "ui/gfx/x/x11_switches.h" // nogncheck
69 #endif 56 #endif
70 57
71 #if defined(OS_LINUX) 58 #if defined(OS_LINUX)
72 #include "content/public/common/sandbox_init.h" 59 #include "content/public/common/sandbox_init.h"
73 #endif 60 #endif
74 61
75 #if defined(OS_MACOSX) 62 #if defined(OS_MACOSX)
76 #include "base/message_loop/message_pump_mac.h" 63 #include "base/message_loop/message_pump_mac.h"
77 #include "content/common/sandbox_mac.h" 64 #include "content/common/sandbox_mac.h"
78 #endif 65 #endif
79 66
80 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) 67 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
81 #include "media/gpu/vaapi_wrapper.h" 68 #include "media/gpu/vaapi_wrapper.h"
82 #endif 69 #endif
83 70
84 #if defined(SANITIZER_COVERAGE) 71 #if defined(SANITIZER_COVERAGE)
85 #include <sanitizer/common_interface_defs.h> 72 #include <sanitizer/common_interface_defs.h>
86 #include <sanitizer/coverage_interface.h> 73 #include <sanitizer/coverage_interface.h>
87 #endif 74 #endif
88 75
89 namespace content { 76 namespace content {
90 77
91 namespace { 78 namespace {
92 79
93 void GetGpuInfoFromCommandLine(gpu::GPUInfo& gpu_info,
94 const base::CommandLine& command_line);
95 void WarmUpSandbox();
96
97 #if !defined(OS_MACOSX)
98 bool CollectGraphicsInfo(gpu::GPUInfo& gpu_info);
99 #endif
100
101 #if defined(OS_LINUX) 80 #if defined(OS_LINUX)
102 #if !defined(OS_CHROMEOS)
103 bool CanAccessNvidiaDeviceFile();
104 #endif
105 bool StartSandboxLinux(const gpu::GPUInfo&, gpu::GpuWatchdogThread*); 81 bool StartSandboxLinux(const gpu::GPUInfo&, gpu::GpuWatchdogThread*);
106 #elif defined(OS_WIN) 82 #elif defined(OS_WIN)
107 bool StartSandboxWindows(const sandbox::SandboxInterfaceInfo*); 83 bool StartSandboxWindows(const sandbox::SandboxInterfaceInfo*);
108 #endif 84 #endif
109 85
110 base::LazyInstance<GpuChildThread::DeferredMessages> deferred_messages = 86 class ContentGpuInitDelegate : public gpu::GpuInitDelegate {
111 LAZY_INSTANCE_INITIALIZER; 87 public:
88 explicit ContentGpuInitDelegate(const base::CommandLine* command_line)
89 : command_line_(command_line), watchdog_thread_(nullptr) {
90 DCHECK(command_line_);
91 }
92 ~ContentGpuInitDelegate() override {}
112 93
113 bool GpuProcessLogMessageHandler(int severity, 94 #if defined(OS_WIN)
114 const char* file, int line, 95 void set_sandbox_info(sandbox::SandboxInterfaceInfo* sandbox_info) {
115 size_t message_start, 96 sandbox_info_ = sandbox_info;
116 const std::string& str) { 97 }
117 std::string header = str.substr(0, message_start); 98 #endif
118 std::string message = str.substr(message_start); 99
119 deferred_messages.Get().push( 100 private:
120 new GpuHostMsg_OnLogMessage(severity, header, message)); 101 // gpu::GpuInit::Delegate:
121 return false; 102 void OnGpuInfoUpdate(const gpu::GPUInfo& gpu_info) override {
122 } 103 gpu_info_ = gpu_info;
104 GetContentClient()->SetGpuInfo(gpu_info_);
105 }
106
107 void OnGpuWatchdogThreadCreated(gpu::GpuWatchdogThread* thread) override {
108 watchdog_thread_ = thread;
109 }
110
111 void OnGpuWatchdogThreadDestroyed() override { watchdog_thread_ = nullptr; }
112
113 bool ShouldInitializeGL() override {
114 #if defined(OS_MACOSX)
115 // On Mac, if the sandbox is enabled, then gl::init::InitializeGLOneOff()
116 // is called from the sandbox warmup code before getting here.
117 if (!command_line_->HasSwitch(switches::kNoSandbox))
118 return false;
119 #endif
120 if (command_line_->HasSwitch(switches::kInProcessGPU)) {
121 // With in-process GPU, gl::init::InitializeGLOneOff() is called from
122 // GpuChildThread before getting here.
123 return false;
124 }
125 return true;
126 }
127
128 void WaitForDebugger() override { ChildProcess::WaitForDebugger("Gpu"); }
129
130 void InitializeMessageLoop() override {
131 #if defined(OS_WIN)
132 // Use a UI message loop because ANGLE and the desktop GL platform can
133 // create child windows to render to.
134 base::MessagePumpForGpu::InitFactory();
135 message_loop_ =
136 base::MakeUnique<base::MessageLoop>(base::MessageLoop::TYPE_UI);
137 #elif defined(OS_LINUX) && defined(USE_X11)
138 // We need a UI loop so that we can grab the Expose events. See GLSurfaceGLX
139 // and https://crbug.com/326995.
140 message_loop_ =
141 base::MakeUnique<base::MessageLoop>(base::MessageLoop::TYPE_UI);
142 std::unique_ptr<ui::PlatformEventSource> event_source =
143 ui::PlatformEventSource::CreateDefault();
144 #elif defined(OS_LINUX)
145 message_loop_ =
146 base::MakeUnique<base::MessageLoop>(base::MessageLoop::TYPE_DEFAULT);
147 #elif defined(OS_MACOSX)
148 // This is necessary for CoreAnimation layers hosted in the GPU process to
149 // be
150 // drawn. See http://crbug.com/312462.
151 std::unique_ptr<base::MessagePump> pump(new base::MessagePumpCFRunLoop());
152 message_loop_ = base::MakeUnique<base::MessageLoop>(std::move(pump));
153 #else
154 message_loop_ =
155 base::MakeUnique<base::MessageLoop>(base::MessageLoop::TYPE_IO);
156 #endif
157 }
158
159 void PreSandboxInitialization() override {
160 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
161 media::VaapiWrapper::PreSandboxInitialization();
162 #endif
163 }
164
165 bool ShouldStartSandboxEarly() override {
166 #if defined(OS_LINUX)
167 // On Chrome OS ARM Mali, GPU driver userspace creates threads when
168 // initializing a GL context, so start the sandbox early.
169 return command_line_->HasSwitch(switches::kGpuSandboxStartEarly);
170 #else
171 return false;
172 #endif
173 }
174
175 void WarmUpSandbox() override {
176 #if defined(OS_WIN)
177 media::DXVAVideoDecodeAccelerator::PreSandboxInitialization();
178 media::MediaFoundationVideoEncodeAccelerator::PreSandboxInitialization();
179 #endif
180 }
181
182 bool StartSandbox() override {
183 #if defined(OS_LINUX)
184 return StartSandboxLinux(gpu_info_, watchdog_thread_);
185 #elif defined(OS_WIN)
186 return StartSandboxWindows(sandbox_info_);
187 #elif defined(OS_MACOSX)
188 return Sandbox::SandboxIsCurrentlyActive();
189 #else
190 return false;
191 #endif
192 }
193
194 void Initialize(base::Time start_time,
195 bool dead_on_arrival,
196 std::vector<gpu::GpuInitLogMessage> init_log_messages,
197 gpu::GpuMemoryBufferFactory* gpu_buffer_factory) override {
198 base::ThreadPriority io_thread_priority = base::ThreadPriority::NORMAL;
199 #if defined(OS_ANDROID) || defined(OS_CHROMEOS)
200 io_thread_priority = base::ThreadPriority::DISPLAY;
201 #endif
202 gpu_process_.reset(new GpuProcess(io_thread_priority));
203
204 GpuChildThread* child_thread =
205 new GpuChildThread(watchdog_thread_, dead_on_arrival, gpu_info_,
206 std::move(init_log_messages), gpu_buffer_factory);
207 child_thread->Init(start_time);
208
209 gpu_process_->set_main_thread(child_thread);
210
211 #if defined(OS_ANDROID)
212 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
213 tracing::GraphicsMemoryDumpProvider::GetInstance(), "AndroidGraphics",
214 nullptr);
215 #endif
216 }
217
218 const base::CommandLine* command_line_;
219 gpu::GpuWatchdogThread* watchdog_thread_ = nullptr;
220 gpu::GPUInfo gpu_info_;
221 std::unique_ptr<base::MessageLoop> message_loop_;
222 std::unique_ptr<GpuProcess> gpu_process_;
223 #if defined(OS_WIN)
224 sandbox::SandboxInterfaceInfo* sandbox_info_ = nullptr;
225 #endif
226
227 DISALLOW_COPY_AND_ASSIGN(ContentGpuInitDelegate);
228 };
123 229
124 } // namespace anonymous 230 } // namespace anonymous
125 231
126 // Main function for starting the Gpu process. 232 // Main function for starting the Gpu process.
127 int GpuMain(const MainFunctionParams& parameters) { 233 int GpuMain(const MainFunctionParams& parameters) {
128 TRACE_EVENT0("gpu", "GpuMain"); 234 TRACE_EVENT0("gpu", "GpuMain");
129 base::trace_event::TraceLog::GetInstance()->SetProcessName("GPU Process"); 235 base::trace_event::TraceLog::GetInstance()->SetProcessName("GPU Process");
130 base::trace_event::TraceLog::GetInstance()->SetProcessSortIndex( 236 base::trace_event::TraceLog::GetInstance()->SetProcessSortIndex(
131 kTraceEventGpuProcessSortIndex); 237 kTraceEventGpuProcessSortIndex);
132 238
133 const base::CommandLine& command_line = parameters.command_line; 239 DCHECK(parameters.command_line.HasSwitch(switches::kGpuVendorID) &&
134 if (command_line.HasSwitch(switches::kGpuStartupDialog)) { 240 parameters.command_line.HasSwitch(switches::kGpuDeviceID) &&
135 ChildProcess::WaitForDebugger("Gpu"); 241 parameters.command_line.HasSwitch(switches::kGpuDriverVersion));
136 } 242 #if defined(USE_X11) && !defined(OS_CHROMEOS)
243 DCHECK(parameters.command_line.HasSwitch(switches::kWindowDepth));
244 DCHECK(parameters.command_line.HasSwitch(switches::kX11VisualID));
245 #endif // defined(USE_X11) && !defined(OS_CHROMEOS)
137 246
138 base::Time start_time = base::Time::Now(); 247 ContentGpuInitDelegate init_delegate(&parameters.command_line);
139
140 #if defined(OS_WIN) 248 #if defined(OS_WIN)
141 // Prevent Windows from displaying a modal dialog on failures like not being 249 init_delegate.set_sandbox_info(parameters.sandbox_info);
142 // able to load a DLL.
143 SetErrorMode(
144 SEM_FAILCRITICALERRORS |
145 SEM_NOGPFAULTERRORBOX |
146 SEM_NOOPENFILEERRORBOX);
147 #elif defined(USE_X11)
148 ui::SetDefaultX11ErrorHandlers();
149
150 #if !defined(OS_CHROMEOS)
151 DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
152 switches::kWindowDepth));
153 DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
154 switches::kX11VisualID));
155 #endif 250 #endif
156 251 gpu::GpuInit gpu_init(&init_delegate, parameters.command_line);
157 #endif
158
159 logging::SetLogMessageHandler(GpuProcessLogMessageHandler);
160
161 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)
167 ui::GpuSwitchingManager::GetInstance()->ForceUseOfDiscreteGpu();
168 else if (workarounds.count(gpu::FORCE_INTEGRATED_GPU) == 1)
169 ui::GpuSwitchingManager::GetInstance()->ForceUseOfIntegratedGpu();
170 }
171
172 // 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
183 #if defined(OS_WIN)
184 // Use a UI message loop because ANGLE and the desktop GL platform can
185 // create child windows to render to.
186 base::MessagePumpForGpu::InitFactory();
187 base::MessageLoop main_message_loop(base::MessageLoop::TYPE_UI);
188 #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);
192 std::unique_ptr<ui::PlatformEventSource> event_source =
193 ui::PlatformEventSource::CreateDefault();
194 #elif defined(OS_LINUX)
195 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.
199 std::unique_ptr<base::MessagePump> pump(new base::MessagePumpCFRunLoop());
200 base::MessageLoop main_message_loop(std::move(pump));
201 #else
202 base::MessageLoop main_message_loop(base::MessageLoop::TYPE_IO);
203 #endif
204
205 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 =
211 !command_line.HasSwitch(switches::kDisableGpuWatchdog) &&
212 !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
220 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
228 scoped_refptr<gpu::GpuWatchdogThread> watchdog_thread;
229
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.
232 if (enable_watchdog && !delayed_watchdog_enable)
233 watchdog_thread = gpu::GpuWatchdogThread::Create();
234
235 // Initializes StatisticsRecorder which tracks UMA histograms.
236 base::StatisticsRecorder::Initialize();
237
238 gpu::GPUInfo gpu_info;
239 // Get vendor_id, device_id, driver_version from browser process through
240 // commandline switches.
241 GetGpuInfoFromCommandLine(gpu_info, command_line);
242 gpu_info.in_process_gpu = false;
243
244 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
245 media::VaapiWrapper::PreSandboxInitialization();
246 #endif
247
248 #if defined(OS_ANDROID) || defined(OS_CHROMEOS)
249 // Set thread priority before sandbox initialization.
250 base::PlatformThread::SetCurrentThreadPriority(base::ThreadPriority::DISPLAY);
251 #endif
252
253 // Warm up resources that don't need access to GPUInfo.
254 WarmUpSandbox();
255
256 #if defined(OS_LINUX)
257 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 }
264 #endif // defined(OS_LINUX)
265
266 base::TimeTicks before_initialize_one_off = base::TimeTicks::Now();
267
268 // Determine if we need to initialize GL here or it has already been done.
269 bool gl_already_initialized = false;
270 #if defined(OS_MACOSX)
271 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 }
276 #endif
277 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 }
282
283 // 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();
299 #if !defined(OS_MACOSX)
300 if (!CollectGraphicsInfo(gpu_info))
301 dead_on_arrival = true;
302
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));
314 }
315 #endif // !defined(OS_MACOSX)
316
317 #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)
322
323 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";
328 dead_on_arrival = true;
329 }
330
331 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);
335 if (enable_watchdog && delayed_watchdog_enable)
336 watchdog_thread = gpu::GpuWatchdogThread::Create();
337
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
355 logging::SetLogMessageHandler(NULL);
356
357 std::unique_ptr<gpu::GpuMemoryBufferFactory> gpu_memory_buffer_factory;
358 if (gpu::GetNativeGpuMemoryBufferType() != gfx::EMPTY_BUFFER)
359 gpu_memory_buffer_factory = gpu::GpuMemoryBufferFactory::CreateNativeType();
360
361 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);
367
368 GpuChildThread* child_thread = new GpuChildThread(
369 watchdog_thread.get(), dead_on_arrival, gpu_info, deferred_messages.Get(),
370 gpu_memory_buffer_factory.get());
371 while (!deferred_messages.Get().empty())
372 deferred_messages.Get().pop();
373
374 child_thread->Init(start_time);
375
376 gpu_process.set_main_thread(child_thread);
377
378 if (watchdog_thread.get())
379 watchdog_thread->AddPowerObserver();
380
381 #if defined(OS_ANDROID)
382 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
383 tracing::GraphicsMemoryDumpProvider::GetInstance(), "AndroidGraphics",
384 nullptr);
385 #endif
386
387 { 252 {
388 TRACE_EVENT0("gpu", "Run Message Loop"); 253 TRACE_EVENT0("gpu", "Run Message Loop");
389 base::RunLoop().Run(); 254 base::RunLoop().Run();
390 } 255 }
391 256
392 child_thread->StopWatchdog(); 257 return 0;
393
394 return dead_on_arrival ? 2 : 0;
395 } 258 }
396 259
397 namespace { 260 namespace {
398 261
399 void GetGpuInfoFromCommandLine(gpu::GPUInfo& gpu_info,
400 const base::CommandLine& command_line) {
401 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);
416 gpu_info.driver_date =
417 command_line.GetSwitchValueASCII(switches::kGpuDriverDate);
418 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
447 GetContentClient()->SetGpuInfo(gpu_info);
448 }
449
450 void WarmUpSandbox() {
451 {
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 }
457
458 #if defined(OS_WIN)
459 media::DXVAVideoDecodeAccelerator::PreSandboxInitialization();
460 media::MediaFoundationVideoEncodeAccelerator::PreSandboxInitialization();
461 #endif
462 }
463
464 #if !defined(OS_MACOSX)
465 bool CollectGraphicsInfo(gpu::GPUInfo& gpu_info) {
466 TRACE_EVENT0("gpu,startup", "Collect Graphics Info");
467
468 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:
476 DVLOG(1) << "gpu::CollectGraphicsInfo failed (non-fatal).";
477 break;
478 case gpu::kCollectInfoNone:
479 NOTREACHED();
480 break;
481 case gpu::kCollectInfoSuccess:
482 break;
483 }
484 GetContentClient()->SetGpuInfo(gpu_info);
485 return res;
486 }
487 #endif
488
489 #if defined(OS_LINUX) 262 #if defined(OS_LINUX)
490 #if !defined(OS_CHROMEOS)
491 bool CanAccessNvidiaDeviceFile() {
492 bool res = true;
493 base::ThreadRestrictions::AssertIOAllowed();
494 if (access("/dev/nvidiactl", R_OK) != 0) {
495 DVLOG(1) << "NVIDIA device file /dev/nvidiactl access denied";
496 res = false;
497 }
498 return res;
499 }
500 #endif
501
502 bool StartSandboxLinux(const gpu::GPUInfo& gpu_info, 263 bool StartSandboxLinux(const gpu::GPUInfo& gpu_info,
503 gpu::GpuWatchdogThread* watchdog_thread) { 264 gpu::GpuWatchdogThread* watchdog_thread) {
504 TRACE_EVENT0("gpu,startup", "Initialize sandbox"); 265 TRACE_EVENT0("gpu,startup", "Initialize sandbox");
505 266
506 bool res = false; 267 bool res = false;
507 268
508 if (watchdog_thread) { 269 if (watchdog_thread) {
509 // LinuxSandbox needs to be able to ensure that the thread 270 // LinuxSandbox needs to be able to ensure that the thread
510 // has really been stopped. 271 // has really been stopped.
511 LinuxSandbox::StopThread(watchdog_thread); 272 LinuxSandbox::StopThread(watchdog_thread);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 return true; 308 return true;
548 } 309 }
549 310
550 return false; 311 return false;
551 } 312 }
552 #endif // defined(OS_WIN) 313 #endif // defined(OS_WIN)
553 314
554 } // namespace. 315 } // namespace.
555 316
556 } // namespace content 317 } // namespace content
OLDNEW
« no previous file with comments | « content/gpu/gpu_child_thread.cc ('k') | content/public/common/content_switches.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698