OLD | NEW |
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 <stdlib.h> | 5 #include <stdlib.h> |
6 | 6 |
7 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
8 #include <dwmapi.h> | 8 #include <dwmapi.h> |
9 #include <windows.h> | 9 #include <windows.h> |
10 #endif | 10 #endif |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 #if defined(ADDRESS_SANITIZER) | 59 #if defined(ADDRESS_SANITIZER) |
60 #include <sanitizer/asan_interface.h> | 60 #include <sanitizer/asan_interface.h> |
61 #endif | 61 #endif |
62 | 62 |
63 const int kGpuTimeout = 10000; | 63 const int kGpuTimeout = 10000; |
64 | 64 |
65 namespace content { | 65 namespace content { |
66 | 66 |
67 namespace { | 67 namespace { |
68 | 68 |
| 69 void GetGpuInfoFromCommandLine(gpu::GPUInfo& gpu_info, |
| 70 const CommandLine& command_line); |
69 bool WarmUpSandbox(const CommandLine& command_line); | 71 bool WarmUpSandbox(const CommandLine& command_line); |
| 72 |
| 73 #if !defined(OS_MACOSX) |
| 74 bool CollectGraphicsInfo(gpu::GPUInfo& gpu_info); |
| 75 #endif |
| 76 |
70 #if defined(OS_LINUX) | 77 #if defined(OS_LINUX) |
| 78 #if !defined(OS_CHROMEOS) |
| 79 bool CanAccessNvidiaDeviceFile(); |
| 80 #endif |
71 bool StartSandboxLinux(const gpu::GPUInfo&, GpuWatchdogThread*, bool); | 81 bool StartSandboxLinux(const gpu::GPUInfo&, GpuWatchdogThread*, bool); |
72 #elif defined(OS_WIN) | 82 #elif defined(OS_WIN) |
73 bool StartSandboxWindows(const sandbox::SandboxInterfaceInfo*); | 83 bool StartSandboxWindows(const sandbox::SandboxInterfaceInfo*); |
74 #endif | 84 #endif |
75 | 85 |
76 base::LazyInstance<GpuChildThread::DeferredMessages> deferred_messages = | 86 base::LazyInstance<GpuChildThread::DeferredMessages> deferred_messages = |
77 LAZY_INSTANCE_INITIALIZER; | 87 LAZY_INSTANCE_INITIALIZER; |
78 | 88 |
79 bool GpuProcessLogMessageHandler(int severity, | 89 bool GpuProcessLogMessageHandler(int severity, |
80 const char* file, int line, | 90 const char* file, int line, |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 // Start the GPU watchdog only after anything that is expected to be time | 204 // Start the GPU watchdog only after anything that is expected to be time |
195 // consuming has completed, otherwise the process is liable to be aborted. | 205 // consuming has completed, otherwise the process is liable to be aborted. |
196 if (enable_watchdog && !delayed_watchdog_enable) { | 206 if (enable_watchdog && !delayed_watchdog_enable) { |
197 watchdog_thread = new GpuWatchdogThread(kGpuTimeout); | 207 watchdog_thread = new GpuWatchdogThread(kGpuTimeout); |
198 watchdog_thread->Start(); | 208 watchdog_thread->Start(); |
199 } | 209 } |
200 | 210 |
201 gpu::GPUInfo gpu_info; | 211 gpu::GPUInfo gpu_info; |
202 // Get vendor_id, device_id, driver_version from browser process through | 212 // Get vendor_id, device_id, driver_version from browser process through |
203 // commandline switches. | 213 // commandline switches. |
204 DCHECK(command_line.HasSwitch(switches::kGpuVendorID) && | 214 GetGpuInfoFromCommandLine(gpu_info, command_line); |
205 command_line.HasSwitch(switches::kGpuDeviceID) && | |
206 command_line.HasSwitch(switches::kGpuDriverVersion)); | |
207 bool success = base::HexStringToUInt( | |
208 command_line.GetSwitchValueASCII(switches::kGpuVendorID), | |
209 &gpu_info.gpu.vendor_id); | |
210 DCHECK(success); | |
211 success = base::HexStringToUInt( | |
212 command_line.GetSwitchValueASCII(switches::kGpuDeviceID), | |
213 &gpu_info.gpu.device_id); | |
214 DCHECK(success); | |
215 gpu_info.driver_vendor = | |
216 command_line.GetSwitchValueASCII(switches::kGpuDriverVendor); | |
217 gpu_info.driver_version = | |
218 command_line.GetSwitchValueASCII(switches::kGpuDriverVersion); | |
219 GetContentClient()->SetGpuInfo(gpu_info); | |
220 | 215 |
221 base::TimeDelta collect_context_time; | 216 base::TimeDelta collect_context_time; |
222 base::TimeDelta initialize_one_off_time; | 217 base::TimeDelta initialize_one_off_time; |
223 | 218 |
224 // Warm up resources that don't need access to GPUInfo. | 219 // Warm up resources that don't need access to GPUInfo. |
225 if (WarmUpSandbox(command_line)) { | 220 if (WarmUpSandbox(command_line)) { |
226 #if defined(OS_LINUX) | 221 #if defined(OS_LINUX) |
227 bool initialized_sandbox = false; | 222 bool initialized_sandbox = false; |
228 bool initialized_gl_context = false; | 223 bool initialized_gl_context = false; |
229 bool should_initialize_gl_context = false; | 224 bool should_initialize_gl_context = false; |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 // purposes. However, on Mac we don't actually use them. As documented in | 261 // purposes. However, on Mac we don't actually use them. As documented in |
267 // crbug.com/222934, due to some driver issues, glGetString could take | 262 // crbug.com/222934, due to some driver issues, glGetString could take |
268 // multiple seconds to finish, which in turn cause the GPU process to | 263 // multiple seconds to finish, which in turn cause the GPU process to |
269 // crash. | 264 // crash. |
270 // By skipping the following code on Mac, we don't really lose anything, | 265 // By skipping the following code on Mac, we don't really lose anything, |
271 // because the basic GPU information is passed down from browser process | 266 // because the basic GPU information is passed down from browser process |
272 // and we already registered them through SetGpuInfo() above. | 267 // and we already registered them through SetGpuInfo() above. |
273 base::TimeTicks before_collect_context_graphics_info = | 268 base::TimeTicks before_collect_context_graphics_info = |
274 base::TimeTicks::Now(); | 269 base::TimeTicks::Now(); |
275 #if !defined(OS_MACOSX) | 270 #if !defined(OS_MACOSX) |
276 gpu::CollectInfoResult result = | 271 if (!CollectGraphicsInfo(gpu_info)) |
277 gpu::CollectContextGraphicsInfo(&gpu_info); | 272 dead_on_arrival = true; |
278 switch (result) { | |
279 case gpu::kCollectInfoFatalFailure: | |
280 LOG(ERROR) << "gpu::CollectGraphicsInfo failed (fatal)."; | |
281 dead_on_arrival = true; | |
282 break; | |
283 case gpu::kCollectInfoNonFatalFailure: | |
284 VLOG(1) << "gpu::CollectGraphicsInfo failed (non-fatal)."; | |
285 break; | |
286 case gpu::kCollectInfoSuccess: | |
287 break; | |
288 } | |
289 GetContentClient()->SetGpuInfo(gpu_info); | |
290 | 273 |
291 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) | 274 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) |
292 // Recompute gpu driver bug workarounds - this is specifically useful | 275 // Recompute gpu driver bug workarounds - this is specifically useful |
293 // on systems where vendor_id/device_id aren't available. | 276 // on systems where vendor_id/device_id aren't available. |
294 if (!command_line.HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) { | 277 if (!command_line.HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) { |
295 gpu::ApplyGpuDriverBugWorkarounds( | 278 gpu::ApplyGpuDriverBugWorkarounds( |
296 gpu_info, const_cast<CommandLine*>(&command_line)); | 279 gpu_info, const_cast<CommandLine*>(&command_line)); |
297 } | 280 } |
298 #endif | 281 #endif |
299 | 282 |
300 #if defined(OS_LINUX) | 283 #if defined(OS_LINUX) |
301 initialized_gl_context = true; | 284 initialized_gl_context = true; |
302 #if !defined(OS_CHROMEOS) | 285 #if !defined(OS_CHROMEOS) |
303 if (gpu_info.gpu.vendor_id == 0x10de && // NVIDIA | 286 if (gpu_info.gpu.vendor_id == 0x10de && // NVIDIA |
304 gpu_info.driver_vendor == "NVIDIA") { | 287 gpu_info.driver_vendor == "NVIDIA" && |
305 base::ThreadRestrictions::AssertIOAllowed(); | 288 !CanAccessNvidiaDeviceFile()) |
306 if (access("/dev/nvidiactl", R_OK) != 0) { | 289 dead_on_arrival = true; |
307 VLOG(1) << "NVIDIA device file /dev/nvidiactl access denied"; | |
308 dead_on_arrival = true; | |
309 } | |
310 } | |
311 #endif // !defined(OS_CHROMEOS) | 290 #endif // !defined(OS_CHROMEOS) |
312 #endif // defined(OS_LINUX) | 291 #endif // defined(OS_LINUX) |
313 #endif // !defined(OS_MACOSX) | 292 #endif // !defined(OS_MACOSX) |
314 collect_context_time = | 293 collect_context_time = |
315 base::TimeTicks::Now() - before_collect_context_graphics_info; | 294 base::TimeTicks::Now() - before_collect_context_graphics_info; |
316 } else { | 295 } else { // gl_initialized |
317 VLOG(1) << "gfx::GLSurface::InitializeOneOff failed"; | 296 VLOG(1) << "gfx::GLSurface::InitializeOneOff failed"; |
318 dead_on_arrival = true; | 297 dead_on_arrival = true; |
319 } | 298 } |
320 | 299 |
321 initialize_one_off_time = | 300 initialize_one_off_time = |
322 base::TimeTicks::Now() - before_initialize_one_off; | 301 base::TimeTicks::Now() - before_initialize_one_off; |
323 | 302 |
324 if (enable_watchdog && delayed_watchdog_enable) { | 303 if (enable_watchdog && delayed_watchdog_enable) { |
325 watchdog_thread = new GpuWatchdogThread(kGpuTimeout); | 304 watchdog_thread = new GpuWatchdogThread(kGpuTimeout); |
326 watchdog_thread->Start(); | 305 watchdog_thread->Start(); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
377 main_message_loop.Run(); | 356 main_message_loop.Run(); |
378 } | 357 } |
379 | 358 |
380 child_thread->StopWatchdog(); | 359 child_thread->StopWatchdog(); |
381 | 360 |
382 return 0; | 361 return 0; |
383 } | 362 } |
384 | 363 |
385 namespace { | 364 namespace { |
386 | 365 |
| 366 void GetGpuInfoFromCommandLine(gpu::GPUInfo& gpu_info, |
| 367 const CommandLine& command_line) { |
| 368 DCHECK(command_line.HasSwitch(switches::kGpuVendorID) && |
| 369 command_line.HasSwitch(switches::kGpuDeviceID) && |
| 370 command_line.HasSwitch(switches::kGpuDriverVersion)); |
| 371 bool success = base::HexStringToUInt( |
| 372 command_line.GetSwitchValueASCII(switches::kGpuVendorID), |
| 373 &gpu_info.gpu.vendor_id); |
| 374 DCHECK(success); |
| 375 success = base::HexStringToUInt( |
| 376 command_line.GetSwitchValueASCII(switches::kGpuDeviceID), |
| 377 &gpu_info.gpu.device_id); |
| 378 DCHECK(success); |
| 379 gpu_info.driver_vendor = |
| 380 command_line.GetSwitchValueASCII(switches::kGpuDriverVendor); |
| 381 gpu_info.driver_version = |
| 382 command_line.GetSwitchValueASCII(switches::kGpuDriverVersion); |
| 383 GetContentClient()->SetGpuInfo(gpu_info); |
| 384 } |
| 385 |
| 386 bool WarmUpSandbox(const CommandLine& command_line) { |
| 387 { |
| 388 TRACE_EVENT0("gpu", "Warm up rand"); |
| 389 // Warm up the random subsystem, which needs to be done pre-sandbox on all |
| 390 // platforms. |
| 391 (void) base::RandUint64(); |
| 392 } |
| 393 return true; |
| 394 } |
| 395 |
| 396 #if !defined(OS_MACOSX) |
| 397 bool CollectGraphicsInfo(gpu::GPUInfo& gpu_info) { |
| 398 bool res = true; |
| 399 gpu::CollectInfoResult result = gpu::CollectContextGraphicsInfo(&gpu_info); |
| 400 switch (result) { |
| 401 case gpu::kCollectInfoFatalFailure: |
| 402 LOG(ERROR) << "gpu::CollectGraphicsInfo failed (fatal)."; |
| 403 res = false; |
| 404 break; |
| 405 case gpu::kCollectInfoNonFatalFailure: |
| 406 VLOG(1) << "gpu::CollectGraphicsInfo failed (non-fatal)."; |
| 407 break; |
| 408 case gpu::kCollectInfoSuccess: |
| 409 break; |
| 410 } |
| 411 GetContentClient()->SetGpuInfo(gpu_info); |
| 412 return res; |
| 413 } |
| 414 #endif |
| 415 |
387 #if defined(OS_LINUX) | 416 #if defined(OS_LINUX) |
| 417 #if !defined(OS_CHROMEOS) |
| 418 bool CanAccessNvidiaDeviceFile() { |
| 419 bool res = true; |
| 420 base::ThreadRestrictions::AssertIOAllowed(); |
| 421 if (access("/dev/nvidiactl", R_OK) != 0) { |
| 422 VLOG(1) << "NVIDIA device file /dev/nvidiactl access denied"; |
| 423 res = false; |
| 424 } |
| 425 return res; |
| 426 } |
| 427 #endif |
| 428 |
388 void CreateDummyGlContext() { | 429 void CreateDummyGlContext() { |
389 scoped_refptr<gfx::GLSurface> surface( | 430 scoped_refptr<gfx::GLSurface> surface( |
390 gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size())); | 431 gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size())); |
391 if (!surface.get()) { | 432 if (!surface.get()) { |
392 VLOG(1) << "gfx::GLSurface::CreateOffscreenGLSurface failed"; | 433 VLOG(1) << "gfx::GLSurface::CreateOffscreenGLSurface failed"; |
393 return; | 434 return; |
394 } | 435 } |
395 | 436 |
396 // On Linux, this is needed to make sure /dev/nvidiactl has | 437 // On Linux, this is needed to make sure /dev/nvidiactl has |
397 // been opened and its descriptor cached. | 438 // been opened and its descriptor cached. |
398 scoped_refptr<gfx::GLContext> context(gfx::GLContext::CreateGLContext( | 439 scoped_refptr<gfx::GLContext> context(gfx::GLContext::CreateGLContext( |
399 NULL, surface.get(), gfx::PreferDiscreteGpu)); | 440 NULL, surface.get(), gfx::PreferDiscreteGpu)); |
400 if (!context.get()) { | 441 if (!context.get()) { |
401 VLOG(1) << "gfx::GLContext::CreateGLContext failed"; | 442 VLOG(1) << "gfx::GLContext::CreateGLContext failed"; |
402 return; | 443 return; |
403 } | 444 } |
404 | 445 |
405 // Similarly, this is needed for /dev/nvidia0. | 446 // Similarly, this is needed for /dev/nvidia0. |
406 if (context->MakeCurrent(surface.get())) { | 447 if (context->MakeCurrent(surface.get())) { |
407 context->ReleaseCurrent(surface.get()); | 448 context->ReleaseCurrent(surface.get()); |
408 } else { | 449 } else { |
409 VLOG(1) << "gfx::GLContext::MakeCurrent failed"; | 450 VLOG(1) << "gfx::GLContext::MakeCurrent failed"; |
410 } | 451 } |
411 } | 452 } |
412 #endif | |
413 | 453 |
414 bool WarmUpSandbox(const CommandLine& command_line) { | |
415 { | |
416 TRACE_EVENT0("gpu", "Warm up rand"); | |
417 // Warm up the random subsystem, which needs to be done pre-sandbox on all | |
418 // platforms. | |
419 (void) base::RandUint64(); | |
420 } | |
421 return true; | |
422 } | |
423 | |
424 #if defined(OS_LINUX) | |
425 void WarmUpSandboxNvidia(const gpu::GPUInfo& gpu_info, | 454 void WarmUpSandboxNvidia(const gpu::GPUInfo& gpu_info, |
426 bool should_initialize_gl_context) { | 455 bool should_initialize_gl_context) { |
427 // We special case Optimus since the vendor_id we see may not be Nvidia. | 456 // We special case Optimus since the vendor_id we see may not be Nvidia. |
428 bool uses_nvidia_driver = (gpu_info.gpu.vendor_id == 0x10de && // NVIDIA. | 457 bool uses_nvidia_driver = (gpu_info.gpu.vendor_id == 0x10de && // NVIDIA. |
429 gpu_info.driver_vendor == "NVIDIA") || | 458 gpu_info.driver_vendor == "NVIDIA") || |
430 gpu_info.optimus; | 459 gpu_info.optimus; |
431 if (uses_nvidia_driver && should_initialize_gl_context) { | 460 if (uses_nvidia_driver && should_initialize_gl_context) { |
432 // We need this on Nvidia to pre-open /dev/nvidiactl and /dev/nvidia0. | 461 // We need this on Nvidia to pre-open /dev/nvidiactl and /dev/nvidia0. |
433 CreateDummyGlContext(); | 462 CreateDummyGlContext(); |
434 } | 463 } |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
483 return true; | 512 return true; |
484 } | 513 } |
485 | 514 |
486 return false; | 515 return false; |
487 } | 516 } |
488 #endif // defined(OS_WIN) | 517 #endif // defined(OS_WIN) |
489 | 518 |
490 } // namespace. | 519 } // namespace. |
491 | 520 |
492 } // namespace content | 521 } // namespace content |
OLD | NEW |