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 <windows.h> | 8 #include <windows.h> |
9 #endif | 9 #endif |
10 | 10 |
(...skipping 26 matching lines...) Expand all Loading... |
37 #endif | 37 #endif |
38 | 38 |
39 #if defined(USE_X11) | 39 #if defined(USE_X11) |
40 #include "ui/base/x/x11_util.h" | 40 #include "ui/base/x/x11_util.h" |
41 #endif | 41 #endif |
42 | 42 |
43 #if defined(OS_LINUX) | 43 #if defined(OS_LINUX) |
44 #include "content/public/common/sandbox_init.h" | 44 #include "content/public/common/sandbox_init.h" |
45 #endif | 45 #endif |
46 | 46 |
| 47 namespace { |
| 48 void WarmUpSandbox(const content::GPUInfo&, bool); |
| 49 void CollectGraphicsInfo(content::GPUInfo*); |
| 50 } |
| 51 |
47 // Main function for starting the Gpu process. | 52 // Main function for starting the Gpu process. |
48 int GpuMain(const content::MainFunctionParams& parameters) { | 53 int GpuMain(const content::MainFunctionParams& parameters) { |
49 TRACE_EVENT0("gpu", "GpuMain"); | 54 TRACE_EVENT0("gpu", "GpuMain"); |
50 | 55 |
51 base::Time start_time = base::Time::Now(); | 56 base::Time start_time = base::Time::Now(); |
52 | 57 |
53 const CommandLine& command_line = parameters.command_line; | 58 const CommandLine& command_line = parameters.command_line; |
54 if (command_line.HasSwitch(switches::kGpuStartupDialog)) { | 59 if (command_line.HasSwitch(switches::kGpuStartupDialog)) { |
55 ChildProcess::WaitForDebugger("Gpu"); | 60 ChildProcess::WaitForDebugger("Gpu"); |
56 } | 61 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 success = base::HexStringToInt( | 97 success = base::HexStringToInt( |
93 command_line.GetSwitchValueASCII(switches::kGpuDeviceID), | 98 command_line.GetSwitchValueASCII(switches::kGpuDeviceID), |
94 reinterpret_cast<int*>(&(gpu_info.gpu.device_id))); | 99 reinterpret_cast<int*>(&(gpu_info.gpu.device_id))); |
95 DCHECK(success); | 100 DCHECK(success); |
96 gpu_info.driver_vendor = | 101 gpu_info.driver_vendor = |
97 command_line.GetSwitchValueASCII(switches::kGpuDriverVendor); | 102 command_line.GetSwitchValueASCII(switches::kGpuDriverVendor); |
98 gpu_info.driver_version = | 103 gpu_info.driver_version = |
99 command_line.GetSwitchValueASCII(switches::kGpuDriverVersion); | 104 command_line.GetSwitchValueASCII(switches::kGpuDriverVersion); |
100 content::GetContentClient()->SetGpuInfo(gpu_info); | 105 content::GetContentClient()->SetGpuInfo(gpu_info); |
101 | 106 |
| 107 // We need to track that information for the WarmUpSandbox function. |
| 108 bool initialized_gl_context = false; |
102 // Load and initialize the GL implementation and locate the GL entry points. | 109 // Load and initialize the GL implementation and locate the GL entry points. |
103 if (gfx::GLSurface::InitializeOneOff()) { | 110 if (gfx::GLSurface::InitializeOneOff()) { |
104 #if defined(OS_LINUX) | 111 #if defined(OS_LINUX) |
105 // We collect full GPU info on demand in Win/Mac, i.e., when about:gpu | 112 // We collect full GPU info on demand in Win/Mac, i.e., when about:gpu |
106 // page opens. This is because we can make blacklist decisions based on | 113 // page opens. This is because we can make blacklist decisions based on |
107 // preliminary GPU info. | 114 // preliminary GPU info. |
108 // However, on Linux, we may not have enough info for blacklisting. | 115 // However, on Linux, we may not have enough info for blacklisting. |
109 if (!gpu_info.gpu.vendor_id || !gpu_info.gpu.device_id || | 116 if (!gpu_info.gpu.vendor_id || !gpu_info.gpu.device_id || |
110 gpu_info.driver_vendor.empty() || gpu_info.driver_version.empty()) { | 117 gpu_info.driver_vendor.empty() || gpu_info.driver_version.empty()) { |
111 if (!gpu_info_collector::CollectGraphicsInfo(&gpu_info)) | 118 CollectGraphicsInfo(&gpu_info); |
112 VLOG(1) << "gpu_info_collector::CollectGraphicsInfo failed"; | 119 // We know that CollectGraphicsInfo will initialize a GLContext. |
113 content::GetContentClient()->SetGpuInfo(gpu_info); | 120 initialized_gl_context = true; |
114 } | 121 } |
115 | 122 |
116 #if !defined(OS_CHROMEOS) | 123 #if !defined(OS_CHROMEOS) |
117 if (gpu_info.gpu.vendor_id == 0x10de && // NVIDIA | 124 if (gpu_info.gpu.vendor_id == 0x10de && // NVIDIA |
118 gpu_info.driver_vendor == "NVIDIA") { | 125 gpu_info.driver_vendor == "NVIDIA") { |
119 base::ThreadRestrictions::AssertIOAllowed(); | 126 base::ThreadRestrictions::AssertIOAllowed(); |
120 if (access("/dev/nvidiactl", R_OK) != 0) { | 127 if (access("/dev/nvidiactl", R_OK) != 0) { |
121 VLOG(1) << "NVIDIA device file /dev/nvidiactl access denied"; | 128 VLOG(1) << "NVIDIA device file /dev/nvidiactl access denied"; |
122 gpu_info.gpu_accessible = false; | 129 gpu_info.gpu_accessible = false; |
123 dead_on_arrival = true; | 130 dead_on_arrival = true; |
124 } | 131 } |
125 } | 132 } |
126 #endif // OS_CHROMEOS | 133 #endif // OS_CHROMEOS |
127 #endif // OS_LINUX | 134 #endif // OS_LINUX |
128 } else { | 135 } else { |
129 VLOG(1) << "gfx::GLSurface::InitializeOneOff failed"; | 136 VLOG(1) << "gfx::GLSurface::InitializeOneOff failed"; |
130 gpu_info.gpu_accessible = false; | 137 gpu_info.gpu_accessible = false; |
131 gpu_info.finalized = true; | 138 gpu_info.finalized = true; |
132 dead_on_arrival = true; | 139 dead_on_arrival = true; |
133 } | 140 } |
134 | 141 |
135 { | 142 { |
136 TRACE_EVENT0("gpu", "Warm up rand"); | 143 const bool should_initialize_gl_context = !initialized_gl_context && |
137 // Warm up the random subsystem, which needs to be done pre-sandbox on all | 144 !dead_on_arrival; |
138 // platforms. | 145 // Warm up the current process before enabling the sandbox. |
139 (void) base::RandUint64(); | 146 WarmUpSandbox(gpu_info, should_initialize_gl_context); |
140 } | |
141 { | |
142 TRACE_EVENT0("gpu", "Warm up HMAC"); | |
143 // Warm up the crypto subsystem, which needs to done pre-sandbox on all | |
144 // platforms. | |
145 crypto::HMAC hmac(crypto::HMAC::SHA256); | |
146 unsigned char key = '\0'; | |
147 bool ret = hmac.Init(&key, sizeof(key)); | |
148 (void) ret; | |
149 } | 147 } |
150 | 148 |
151 #if defined(OS_LINUX) | 149 #if defined(OS_LINUX) |
152 { | 150 { |
153 TRACE_EVENT0("gpu", "Initialize sandbox"); | 151 TRACE_EVENT0("gpu", "Initialize sandbox"); |
154 bool do_init_sandbox = true; | 152 bool do_init_sandbox = true; |
155 | 153 |
156 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) | |
157 OmxVideoDecodeAccelerator::PreSandboxInitialization(); | |
158 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) | |
159 VaapiVideoDecodeAccelerator::PreSandboxInitialization(); | |
160 #endif | |
161 | |
162 #if defined(OS_CHROMEOS) && defined(NDEBUG) | 154 #if defined(OS_CHROMEOS) && defined(NDEBUG) |
163 // On Chrome OS and when not on a debug build, initialize | 155 // On Chrome OS and when not on a debug build, initialize |
164 // the GPU process' sandbox only for Intel GPUs. | 156 // the GPU process' sandbox only for Intel GPUs. |
165 do_init_sandbox = gpu_info.gpu.vendor_id == 0x8086; // Intel GPU. | 157 do_init_sandbox = gpu_info.gpu.vendor_id == 0x8086; // Intel GPU. |
166 #endif | 158 #endif |
167 | 159 |
168 if (do_init_sandbox) { | 160 if (do_init_sandbox) { |
169 content::InitializeSandbox(); | 161 content::InitializeSandbox(); |
170 } | 162 } |
171 } | 163 } |
172 #endif | 164 #endif |
173 | 165 |
174 { | |
175 TRACE_EVENT0("gpu", "Initialize COM"); | |
176 base::win::ScopedCOMInitializer com_initializer; | |
177 } | |
178 | |
179 #if defined(OS_WIN) | 166 #if defined(OS_WIN) |
180 { | 167 { |
181 TRACE_EVENT0("gpu", "Preload setupapi.dll"); | |
182 // Preload this DLL because the sandbox prevents it from loading. | |
183 LoadLibrary(L"setupapi.dll"); | |
184 } | |
185 | |
186 { | |
187 TRACE_EVENT0("gpu", "Initialize DXVA"); | |
188 // Initialize H/W video decoding stuff which fails in the sandbox. | |
189 DXVAVideoDecodeAccelerator::PreSandboxInitialization(); | |
190 } | |
191 | |
192 { | |
193 TRACE_EVENT0("gpu", "Lower token"); | 168 TRACE_EVENT0("gpu", "Lower token"); |
194 // For windows, if the target_services interface is not zero, the process | 169 // For windows, if the target_services interface is not zero, the process |
195 // is sandboxed and we must call LowerToken() before rendering untrusted | 170 // is sandboxed and we must call LowerToken() before rendering untrusted |
196 // content. | 171 // content. |
197 sandbox::TargetServices* target_services = | 172 sandbox::TargetServices* target_services = |
198 parameters.sandbox_info->target_services; | 173 parameters.sandbox_info->target_services; |
199 if (target_services) | 174 if (target_services) |
200 target_services->LowerToken(); | 175 target_services->LowerToken(); |
201 } | 176 } |
202 #endif | 177 #endif |
(...skipping 25 matching lines...) Expand all Loading... |
228 | 203 |
229 { | 204 { |
230 TRACE_EVENT0("gpu", "Run Message Loop"); | 205 TRACE_EVENT0("gpu", "Run Message Loop"); |
231 main_message_loop.Run(); | 206 main_message_loop.Run(); |
232 } | 207 } |
233 | 208 |
234 child_thread->StopWatchdog(); | 209 child_thread->StopWatchdog(); |
235 | 210 |
236 return 0; | 211 return 0; |
237 } | 212 } |
| 213 |
| 214 namespace { |
| 215 |
| 216 void CreateDummyGlContext() { |
| 217 scoped_refptr<gfx::GLSurface> surface( |
| 218 gfx::GLSurface::CreateOffscreenGLSurface(false, gfx::Size(1, 1))); |
| 219 if (!surface.get()) { |
| 220 VLOG(1) << "gfx::GLSurface::CreateOffscreenGLSurface failed"; |
| 221 return; |
| 222 } |
| 223 |
| 224 // On Linux, this is needed to make sure /dev/nvidiactl has |
| 225 // been opened and its descriptor cached. |
| 226 scoped_refptr<gfx::GLContext> context( |
| 227 gfx::GLContext::CreateGLContext(NULL, |
| 228 surface, |
| 229 gfx::PreferDiscreteGpu)); |
| 230 if (!context.get()) { |
| 231 VLOG(1) << "gfx::GLContext::CreateGLContext failed"; |
| 232 return; |
| 233 } |
| 234 |
| 235 // Similarly, this is needed for /dev/nvidia0. |
| 236 if (context->MakeCurrent(surface)) { |
| 237 context->ReleaseCurrent(surface.get()); |
| 238 } else { |
| 239 VLOG(1) << "gfx::GLContext::MakeCurrent failed"; |
| 240 } |
| 241 } |
| 242 |
| 243 void WarmUpSandbox(const content::GPUInfo& gpu_info, |
| 244 bool should_initialize_gl_context) { |
| 245 { |
| 246 TRACE_EVENT0("gpu", "Warm up rand"); |
| 247 // Warm up the random subsystem, which needs to be done pre-sandbox on all |
| 248 // platforms. |
| 249 (void) base::RandUint64(); |
| 250 } |
| 251 { |
| 252 TRACE_EVENT0("gpu", "Warm up HMAC"); |
| 253 // Warm up the crypto subsystem, which needs to done pre-sandbox on all |
| 254 // platforms. |
| 255 crypto::HMAC hmac(crypto::HMAC::SHA256); |
| 256 unsigned char key = '\0'; |
| 257 bool ret = hmac.Init(&key, sizeof(key)); |
| 258 (void) ret; |
| 259 } |
| 260 |
| 261 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) |
| 262 OmxVideoDecodeAccelerator::PreSandboxInitialization(); |
| 263 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) |
| 264 VaapiVideoDecodeAccelerator::PreSandboxInitialization(); |
| 265 #endif |
| 266 |
| 267 #if defined(OS_LINUX) |
| 268 if (gpu_info.gpu.vendor_id == 0x10de && // NVIDIA |
| 269 gpu_info.driver_vendor == "NVIDIA" && |
| 270 should_initialize_gl_context) { |
| 271 // We need this on Nvidia to pre-open /dev/nvidiactl and /dev/nvidia0. |
| 272 CreateDummyGlContext(); |
| 273 } |
| 274 #endif |
| 275 |
| 276 { |
| 277 TRACE_EVENT0("gpu", "Initialize COM"); |
| 278 base::win::ScopedCOMInitializer com_initializer; |
| 279 } |
| 280 |
| 281 #if defined(OS_WIN) |
| 282 { |
| 283 TRACE_EVENT0("gpu", "Preload setupapi.dll"); |
| 284 // Preload this DLL because the sandbox prevents it from loading. |
| 285 LoadLibrary(L"setupapi.dll"); |
| 286 } |
| 287 |
| 288 { |
| 289 TRACE_EVENT0("gpu", "Initialize DXVA"); |
| 290 // Initialize H/W video decoding stuff which fails in the sandbox. |
| 291 DXVAVideoDecodeAccelerator::PreSandboxInitialization(); |
| 292 } |
| 293 #endif |
| 294 } |
| 295 |
| 296 void CollectGraphicsInfo(content::GPUInfo* gpu_info) { |
| 297 if (!gpu_info_collector::CollectGraphicsInfo(gpu_info)) |
| 298 VLOG(1) << "gpu_info_collector::CollectGraphicsInfo failed"; |
| 299 content::GetContentClient()->SetGpuInfo(*gpu_info); |
| 300 } |
| 301 |
| 302 } // namespace. |
| 303 |
OLD | NEW |