15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include <dwmapi.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h" 137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/lazy_instance.h" 149ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/metrics/histogram.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/rand_util.h" 17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h" 21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/child/child_process.h" 227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "content/common/content_constants_internal.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/gpu_config.h" 247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "content/common/gpu/gpu_messages.h" 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/common/gpu/media/gpu_video_encode_accelerator.h" 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/common/sandbox_linux/sandbox_linux.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/gpu/gpu_child_thread.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/gpu/gpu_process.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/gpu/gpu_watchdog_thread.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/content_client.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/content_switches.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/main_function_params.h" 33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "gpu/command_buffer/service/gpu_switches.h" 3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "gpu/config/gpu_info_collector.h" 35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "gpu/config/gpu_util.h" 36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/events/platform/platform_event_source.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_implementation.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_surface.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_switches.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gpu_switching_manager.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 4358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/win/windows_version.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_com_initializer.h" 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/sandbox.h" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_X11) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/x/x11_util.h" 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/sandbox_init.h" 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(OS_MACOSX) 57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/message_loop/message_pump_mac.h" 58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/common/sandbox_mac.h" 59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif 60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 6146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#if defined(ADDRESS_SANITIZER) 6246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include <sanitizer/asan_interface.h> 6346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#endif 6446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kGpuTimeout = 10000; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void GetGpuInfoFromCommandLine(gpu::GPUInfo& gpu_info, 72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const CommandLine& command_line); 737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool WarmUpSandbox(const CommandLine& command_line); 74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if !defined(OS_MACOSX) 76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool CollectGraphicsInfo(gpu::GPUInfo& gpu_info); 77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_LINUX) 80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if !defined(OS_CHROMEOS) 81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool CanAccessNvidiaDeviceFile(); 82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif 8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool StartSandboxLinux(const gpu::GPUInfo&, GpuWatchdogThread*, bool); 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#elif defined(OS_WIN) 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool StartSandboxWindows(const sandbox::SandboxInterfaceInfo*); 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif 877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)base::LazyInstance<GpuChildThread::DeferredMessages> deferred_messages = 897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) LAZY_INSTANCE_INITIALIZER; 907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool GpuProcessLogMessageHandler(int severity, 927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const char* file, int line, 937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) size_t message_start, 947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const std::string& str) { 957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) std::string header = str.substr(0, message_start); 967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) std::string message = str.substr(message_start); 977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) deferred_messages.Get().push(new GpuHostMsg_OnLogMessage( 987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) severity, header, message)); 997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return false; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} // namespace anonymous 1037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Main function for starting the Gpu process. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int GpuMain(const MainFunctionParams& parameters) { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRACE_EVENT0("gpu", "GpuMain"); 1077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::debug::TraceLog::GetInstance()->SetProcessName("GPU Process"); 1087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::debug::TraceLog::GetInstance()->SetProcessSortIndex( 1097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch kTraceEventGpuProcessSortIndex); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CommandLine& command_line = parameters.command_line; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (command_line.HasSwitch(switches::kGpuStartupDialog)) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChildProcess::WaitForDebugger("Gpu"); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Time start_time = base::Time::Now(); 1177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Prevent Windows from displaying a modal dialog on failures like not being 120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // able to load a DLL. 121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SetErrorMode( 122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SEM_FAILCRITICALERRORS | 123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SEM_NOGPFAULTERRORBOX | 124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SEM_NOOPENFILEERRORBOX); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(USE_X11) 126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ui::SetDefaultX11ErrorHandlers(); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) logging::SetLogMessageHandler(GpuProcessLogMessageHandler); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (command_line.HasSwitch(switches::kSupportsDualGpus)) { 132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string types = command_line.GetSwitchValueASCII( 133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) switches::kGpuDriverBugWorkarounds); 134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::set<int> workarounds; 135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) gpu::StringToFeatureSet(types, &workarounds); 136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (workarounds.count(gpu::FORCE_DISCRETE_GPU) == 1) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::GpuSwitchingManager::GetInstance()->ForceUseOfDiscreteGpu(); 138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) else if (workarounds.count(gpu::FORCE_INTEGRATED_GPU) == 1) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::GpuSwitchingManager::GetInstance()->ForceUseOfIntegratedGpu(); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialization of the OpenGL bindings may fail, in which case we 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will need to tear down this process. However, we can not do so 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // safely until the IPC channel is set up, because the detection of 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // early return of a child process is implemented using an IPC 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // channel error. If the IPC channel is not fully set up between the 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // browser and GPU process, and the GPU process crashes or exits 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // early, the browser process will never detect it. For this reason 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we defer tearing down the GPU process until receiving the 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // GpuMsg_Initialize message from the browser. 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool dead_on_arrival = false; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::MessageLoop::Type message_loop_type = base::MessageLoop::TYPE_IO; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unless we're running on desktop GL, we don't need a UI message 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // loop, so avoid its use to work around apparent problems with some 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // third-party software. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (command_line.HasSwitch(switches::kUseGL) && 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_line.GetSwitchValueASCII(switches::kUseGL) == 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::kGLImplementationDesktopName) { 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) message_loop_type = base::MessageLoop::TYPE_UI; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::MessageLoop main_message_loop(message_loop_type); 164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#elif defined(OS_LINUX) && defined(USE_X11) 165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // We need a UI loop so that we can grab the Expose events. See GLSurfaceGLX 166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // and https://crbug.com/326995. 167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::MessageLoop main_message_loop(base::MessageLoop::TYPE_UI); 168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<ui::PlatformEventSource> event_source = 169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ui::PlatformEventSource::CreateDefault(); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_LINUX) 171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::MessageLoop main_message_loop(base::MessageLoop::TYPE_DEFAULT); 172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#elif defined(OS_MACOSX) 173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // This is necessary for CoreAnimation layers hosted in the GPU process to be 174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // drawn. See http://crbug.com/312462. 175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<base::MessagePump> pump(new base::MessagePumpCFRunLoop()); 176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::MessageLoop main_message_loop(pump.Pass()); 177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#else 178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::MessageLoop main_message_loop(base::MessageLoop::TYPE_IO); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PlatformThread::SetName("CrGpuMain"); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In addition to disabling the watchdog if the command line switch is 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // present, disable the watchdog on valgrind because the code is expected 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to run slowly in that case. 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool enable_watchdog = 1877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) !command_line.HasSwitch(switches::kDisableGpuWatchdog) && 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !RunningOnValgrind(); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Disable the watchdog in debug builds because they tend to only be run by 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // developers who will not appreciate the watchdog killing the GPU process. 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enable_watchdog = false; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool delayed_watchdog_enable = false; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't start watchdog immediately, to allow developers to switch to VT2 on 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // startup. 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delayed_watchdog_enable = true; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<GpuWatchdogThread> watchdog_thread; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start the GPU watchdog only after anything that is expected to be time 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // consuming has completed, otherwise the process is liable to be aborted. 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (enable_watchdog && !delayed_watchdog_enable) { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) watchdog_thread = new GpuWatchdogThread(kGpuTimeout); 2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Thread::Options options; 2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci options.timer_slack = base::TIMER_SLACK_MAXIMUM; 2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci watchdog_thread->StartWithOptions(options); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) gpu::GPUInfo gpu_info; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get vendor_id, device_id, driver_version from browser process through 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // commandline switches. 218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GetGpuInfoFromCommandLine(gpu_info, command_line); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 220a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::TimeDelta collect_context_time; 221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::TimeDelta initialize_one_off_time; 222a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Warm up resources that don't need access to GPUInfo. 2247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (WarmUpSandbox(command_line)) { 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_LINUX) 2267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) bool initialized_sandbox = false; 2277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) bool initialized_gl_context = false; 2287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) bool should_initialize_gl_context = false; 229effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // On Chrome OS ARM Mali, GPU driver userspace creates threads when 230effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // initializing a GL context, so start the sandbox early. 231116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (command_line.HasSwitch(switches::kGpuSandboxStartEarly)) { 232116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gpu_info.sandboxed = StartSandboxLinux( 233116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gpu_info, watchdog_thread.get(), should_initialize_gl_context); 234effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch initialized_sandbox = true; 235effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif // defined(OS_LINUX) 237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::TimeTicks before_initialize_one_off = base::TimeTicks::Now(); 239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Determine if we need to initialize GL here or it has already been done. 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool gl_already_initialized = false; 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_MACOSX) 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!command_line.HasSwitch(switches::kNoSandbox)) { 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // On Mac, if the sandbox is enabled, then GLSurface::InitializeOneOff() 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // is called from the sandbox warmup code before getting here. 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gl_already_initialized = true; 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (command_line.HasSwitch(switches::kInProcessGPU)) { 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // With in-process GPU, GLSurface::InitializeOneOff() is called from 2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // GpuChildThread before getting here. 2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gl_already_initialized = true; 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Load and initialize the GL implementation and locate the GL entry points. 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool gl_initialized = 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gl_already_initialized 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ? gfx::GetGLImplementation() != gfx::kGLImplementationNone 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : gfx::GLSurface::InitializeOneOff(); 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (gl_initialized) { 2617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // We need to collect GL strings (VENDOR, RENDERER) for blacklisting 2627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // purposes. However, on Mac we don't actually use them. As documented in 2637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // crbug.com/222934, due to some driver issues, glGetString could take 2647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // multiple seconds to finish, which in turn cause the GPU process to 2657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // crash. 2667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // By skipping the following code on Mac, we don't really lose anything, 2677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // because the basic GPU information is passed down from browser process 2687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // and we already registered them through SetGpuInfo() above. 269a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::TimeTicks before_collect_context_graphics_info = 270a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::TimeTicks::Now(); 271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if !defined(OS_MACOSX) 272f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!CollectGraphicsInfo(gpu_info)) 273f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dead_on_arrival = true; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_CHROMEOS) || defined(OS_ANDROID) 276a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Recompute gpu driver bug workarounds - this is specifically useful 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // on systems where vendor_id/device_id aren't available. 278a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!command_line.HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) { 279a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) gpu::ApplyGpuDriverBugWorkarounds( 280a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) gpu_info, const_cast<CommandLine*>(&command_line)); 281a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 283a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_LINUX) 2857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) initialized_gl_context = true; 286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if !defined(OS_CHROMEOS) 2877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (gpu_info.gpu.vendor_id == 0x10de && // NVIDIA 288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) gpu_info.driver_vendor == "NVIDIA" && 289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) !CanAccessNvidiaDeviceFile()) 290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dead_on_arrival = true; 291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif // !defined(OS_CHROMEOS) 292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif // defined(OS_LINUX) 293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif // !defined(OS_MACOSX) 294a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) collect_context_time = 295a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::TimeTicks::Now() - before_collect_context_graphics_info; 296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else { // gl_initialized 2977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) VLOG(1) << "gfx::GLSurface::InitializeOneOff failed"; 2987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) dead_on_arrival = true; 2997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 301a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) initialize_one_off_time = 302a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::TimeTicks::Now() - before_initialize_one_off; 303a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 3047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (enable_watchdog && delayed_watchdog_enable) { 3057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) watchdog_thread = new GpuWatchdogThread(kGpuTimeout); 3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Thread::Options options; 3071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci options.timer_slack = base::TIMER_SLACK_MAXIMUM; 3081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci watchdog_thread->StartWithOptions(options); 3097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // OSMesa is expected to run very slowly, so disable the watchdog in that 3127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // case. 3137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (enable_watchdog && 3147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) gfx::GetGLImplementation() == gfx::kGLImplementationOSMesaGL) { 3157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) watchdog_thread->Stop(); 3167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) watchdog_thread = NULL; 3177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX) 3207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) should_initialize_gl_context = !initialized_gl_context && 3217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) !dead_on_arrival; 322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!initialized_sandbox) { 3247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) gpu_info.sandboxed = StartSandboxLinux(gpu_info, watchdog_thread.get(), 3257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) should_initialize_gl_context); 3267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#elif defined(OS_WIN) 3287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) gpu_info.sandboxed = StartSandboxWindows(parameters.sandbox_info); 329116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#elif defined(OS_MACOSX) 330116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gpu_info.sandboxed = Sandbox::SandboxIsCurrentlyActive(); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gpu_info.video_encode_accelerator_supported_profiles = 3341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content::GpuVideoEncodeAccelerator::GetSupportedProfiles(); 3357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } else { 3367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) dead_on_arrival = true; 3377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 3387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) logging::SetLogMessageHandler(NULL); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GpuProcess gpu_process; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 343a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // These UMA must be stored after GpuProcess is constructed as it 344a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // initializes StatisticsRecorder which tracks the histograms. 345a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) UMA_HISTOGRAM_TIMES("GPU.CollectContextGraphicsInfo", collect_context_time); 346a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) UMA_HISTOGRAM_TIMES("GPU.InitializeOneOffTime", initialize_one_off_time); 347a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GpuChildThread* child_thread = new GpuChildThread(watchdog_thread.get(), 3497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) dead_on_arrival, 3507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) gpu_info, 3517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) deferred_messages.Get()); 3527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) while (!deferred_messages.Get().empty()) 3537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) deferred_messages.Get().pop(); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child_thread->Init(start_time); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gpu_process.set_main_thread(child_thread); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (watchdog_thread.get()) 3603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch watchdog_thread->AddPowerObserver(); 3613240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRACE_EVENT0("gpu", "Run Message Loop"); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) main_message_loop.Run(); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child_thread->StopWatchdog(); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 374f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void GetGpuInfoFromCommandLine(gpu::GPUInfo& gpu_info, 375f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const CommandLine& command_line) { 376f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK(command_line.HasSwitch(switches::kGpuVendorID) && 377f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) command_line.HasSwitch(switches::kGpuDeviceID) && 378f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) command_line.HasSwitch(switches::kGpuDriverVersion)); 379f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool success = base::HexStringToUInt( 380f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) command_line.GetSwitchValueASCII(switches::kGpuVendorID), 381f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &gpu_info.gpu.vendor_id); 382f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK(success); 383f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) success = base::HexStringToUInt( 384f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) command_line.GetSwitchValueASCII(switches::kGpuDeviceID), 385f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &gpu_info.gpu.device_id); 386f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK(success); 387f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) gpu_info.driver_vendor = 388f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) command_line.GetSwitchValueASCII(switches::kGpuDriverVendor); 389f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) gpu_info.driver_version = 390f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) command_line.GetSwitchValueASCII(switches::kGpuDriverVersion); 391f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GetContentClient()->SetGpuInfo(gpu_info); 392f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 393f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 394f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool WarmUpSandbox(const CommandLine& command_line) { 395f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) { 396f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) TRACE_EVENT0("gpu", "Warm up rand"); 397f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Warm up the random subsystem, which needs to be done pre-sandbox on all 398f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // platforms. 399f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) (void) base::RandUint64(); 400f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 401f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 402f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 403f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 404f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if !defined(OS_MACOSX) 405f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool CollectGraphicsInfo(gpu::GPUInfo& gpu_info) { 406f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool res = true; 407f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) gpu::CollectInfoResult result = gpu::CollectContextGraphicsInfo(&gpu_info); 408f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) switch (result) { 409f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case gpu::kCollectInfoFatalFailure: 410f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LOG(ERROR) << "gpu::CollectGraphicsInfo failed (fatal)."; 411f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) res = false; 412f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 413f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case gpu::kCollectInfoNonFatalFailure: 414f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) VLOG(1) << "gpu::CollectGraphicsInfo failed (non-fatal)."; 415f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 4161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case gpu::kCollectInfoNone: 4171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci NOTREACHED(); 4181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci break; 419f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case gpu::kCollectInfoSuccess: 420f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 421f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 422f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GetContentClient()->SetGpuInfo(gpu_info); 423f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return res; 424f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 425f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif 426f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX) 428f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if !defined(OS_CHROMEOS) 429f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool CanAccessNvidiaDeviceFile() { 430f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool res = true; 431f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 432f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (access("/dev/nvidiactl", R_OK) != 0) { 433f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) VLOG(1) << "NVIDIA device file /dev/nvidiactl access denied"; 434f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) res = false; 435f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 436f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return res; 437f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 438f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif 439f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CreateDummyGlContext() { 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<gfx::GLSurface> surface( 442cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size())); 443868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!surface.get()) { 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "gfx::GLSurface::CreateOffscreenGLSurface failed"; 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // On Linux, this is needed to make sure /dev/nvidiactl has 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // been opened and its descriptor cached. 450868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_refptr<gfx::GLContext> context(gfx::GLContext::CreateGLContext( 451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) NULL, surface.get(), gfx::PreferDiscreteGpu)); 452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!context.get()) { 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "gfx::GLContext::CreateGLContext failed"; 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Similarly, this is needed for /dev/nvidia0. 458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (context->MakeCurrent(surface.get())) { 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context->ReleaseCurrent(surface.get()); 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "gfx::GLContext::MakeCurrent failed"; 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 46590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void WarmUpSandboxNvidia(const gpu::GPUInfo& gpu_info, 466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool should_initialize_gl_context) { 467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We special case Optimus since the vendor_id we see may not be Nvidia. 468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool uses_nvidia_driver = (gpu_info.gpu.vendor_id == 0x10de && // NVIDIA. 469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gpu_info.driver_vendor == "NVIDIA") || 470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gpu_info.optimus; 471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (uses_nvidia_driver && should_initialize_gl_context) { 472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We need this on Nvidia to pre-open /dev/nvidiactl and /dev/nvidia0. 473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CreateDummyGlContext(); 474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 47790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool StartSandboxLinux(const gpu::GPUInfo& gpu_info, 478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GpuWatchdogThread* watchdog_thread, 479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool should_initialize_gl_context) { 480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TRACE_EVENT0("gpu", "Initialize sandbox"); 481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool res = false; 483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) WarmUpSandboxNvidia(gpu_info, should_initialize_gl_context); 485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (watchdog_thread) { 4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // LinuxSandbox needs to be able to ensure that the thread 4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // has really been stopped. 4895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LinuxSandbox::StopThread(watchdog_thread); 4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 49146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 49246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#if defined(ADDRESS_SANITIZER) 49346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const std::string sancov_file_name = 49446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) "gpu." + base::Uint64ToString(base::RandUint64()); 49546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance(); 49646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) linux_sandbox->sanitizer_args()->coverage_sandboxed = 1; 49746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) linux_sandbox->sanitizer_args()->coverage_fd = 49846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) __sanitizer_maybe_open_cov_file(sancov_file_name.c_str()); 49946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) linux_sandbox->sanitizer_args()->coverage_max_block_size = 0; 50046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#endif 50146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 502c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // LinuxSandbox::InitializeSandbox() must always be called 503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // with only one thread. 504c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) res = LinuxSandbox::InitializeSandbox(); 5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (watchdog_thread) { 5061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Thread::Options options; 5071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci options.timer_slack = base::TIMER_SLACK_MAXIMUM; 5081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci watchdog_thread->StartWithOptions(options); 5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return res; 512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif // defined(OS_LINUX) 514c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_WIN) 516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool StartSandboxWindows(const sandbox::SandboxInterfaceInfo* sandbox_info) { 517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TRACE_EVENT0("gpu", "Lower token"); 518c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 519c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // For Windows, if the target_services interface is not zero, the process 520c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // is sandboxed and we must call LowerToken() before rendering untrusted 521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // content. 522c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sandbox::TargetServices* target_services = sandbox_info->target_services; 523c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (target_services) { 524c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) target_services->LowerToken(); 525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 526c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif // defined(OS_WIN) 531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace. 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 535