| 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 <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 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 #include "content/public/common/content_client.h" | 29 #include "content/public/common/content_client.h" |
| 30 #include "content/public/common/content_switches.h" | 30 #include "content/public/common/content_switches.h" |
| 31 #include "content/public/common/main_function_params.h" | 31 #include "content/public/common/main_function_params.h" |
| 32 #include "gpu/command_buffer/service/gpu_switches.h" | 32 #include "gpu/command_buffer/service/gpu_switches.h" |
| 33 #include "gpu/config/gpu_driver_bug_list.h" | 33 #include "gpu/config/gpu_driver_bug_list.h" |
| 34 #include "gpu/config/gpu_info_collector.h" | 34 #include "gpu/config/gpu_info_collector.h" |
| 35 #include "gpu/config/gpu_switches.h" | 35 #include "gpu/config/gpu_switches.h" |
| 36 #include "gpu/config/gpu_util.h" | 36 #include "gpu/config/gpu_util.h" |
| 37 #include "gpu/ipc/common/gpu_memory_buffer_support.h" | 37 #include "gpu/ipc/common/gpu_memory_buffer_support.h" |
| 38 #include "gpu/ipc/service/gpu_config.h" | 38 #include "gpu/ipc/service/gpu_config.h" |
| 39 #include "gpu/ipc/service/gpu_init.h" |
| 39 #include "gpu/ipc/service/gpu_memory_buffer_factory.h" | 40 #include "gpu/ipc/service/gpu_memory_buffer_factory.h" |
| 40 #include "gpu/ipc/service/gpu_watchdog_thread.h" | 41 #include "gpu/ipc/service/gpu_watchdog_thread.h" |
| 41 #include "ui/events/platform/platform_event_source.h" | 42 #include "ui/events/platform/platform_event_source.h" |
| 42 #include "ui/gl/gl_context.h" | 43 #include "ui/gl/gl_context.h" |
| 43 #include "ui/gl/gl_implementation.h" | 44 #include "ui/gl/gl_implementation.h" |
| 44 #include "ui/gl/gl_surface.h" | 45 #include "ui/gl/gl_surface.h" |
| 45 #include "ui/gl/gl_switches.h" | 46 #include "ui/gl/gl_switches.h" |
| 46 #include "ui/gl/gpu_switching_manager.h" | 47 #include "ui/gl/gpu_switching_manager.h" |
| 47 #include "ui/gl/init/gl_factory.h" | 48 #include "ui/gl/init/gl_factory.h" |
| 48 | 49 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 | 85 |
| 85 #if defined(SANITIZER_COVERAGE) | 86 #if defined(SANITIZER_COVERAGE) |
| 86 #include <sanitizer/common_interface_defs.h> | 87 #include <sanitizer/common_interface_defs.h> |
| 87 #include <sanitizer/coverage_interface.h> | 88 #include <sanitizer/coverage_interface.h> |
| 88 #endif | 89 #endif |
| 89 | 90 |
| 90 namespace content { | 91 namespace content { |
| 91 | 92 |
| 92 namespace { | 93 namespace { |
| 93 | 94 |
| 94 void GetGpuInfoFromCommandLine(gpu::GPUInfo& gpu_info, | |
| 95 const base::CommandLine& command_line); | |
| 96 void WarmUpSandbox(); | |
| 97 | |
| 98 #if !defined(OS_MACOSX) | |
| 99 bool CollectGraphicsInfo(gpu::GPUInfo& gpu_info); | |
| 100 #endif | |
| 101 | |
| 102 #if defined(OS_LINUX) | 95 #if defined(OS_LINUX) |
| 103 #if !defined(OS_CHROMEOS) | 96 bool StartSandboxLinux(gpu::GpuWatchdogThread*); |
| 104 bool CanAccessNvidiaDeviceFile(); | |
| 105 #endif | |
| 106 bool StartSandboxLinux(const gpu::GPUInfo&, gpu::GpuWatchdogThread*); | |
| 107 #elif defined(OS_WIN) | 97 #elif defined(OS_WIN) |
| 108 bool StartSandboxWindows(const sandbox::SandboxInterfaceInfo*); | 98 bool StartSandboxWindows(const sandbox::SandboxInterfaceInfo*); |
| 109 #endif | 99 #endif |
| 110 | 100 |
| 111 base::LazyInstance<GpuChildThread::DeferredMessages> deferred_messages = | 101 base::LazyInstance<GpuChildThread::DeferredMessages> deferred_messages = |
| 112 LAZY_INSTANCE_INITIALIZER; | 102 LAZY_INSTANCE_INITIALIZER; |
| 113 | 103 |
| 114 bool GpuProcessLogMessageHandler(int severity, | 104 bool GpuProcessLogMessageHandler(int severity, |
| 115 const char* file, int line, | 105 const char* file, int line, |
| 116 size_t message_start, | 106 size_t message_start, |
| 117 const std::string& str) { | 107 const std::string& str) { |
| 118 std::string header = str.substr(0, message_start); | 108 std::string header = str.substr(0, message_start); |
| 119 std::string message = str.substr(message_start); | 109 std::string message = str.substr(message_start); |
| 120 deferred_messages.Get().push( | 110 deferred_messages.Get().push( |
| 121 new GpuHostMsg_OnLogMessage(severity, header, message)); | 111 new GpuHostMsg_OnLogMessage(severity, header, message)); |
| 122 return false; | 112 return false; |
| 123 } | 113 } |
| 124 | 114 |
| 115 class ContentSandboxHelper : public gpu::GpuSandboxHelper { |
| 116 public: |
| 117 ContentSandboxHelper() {} |
| 118 ~ContentSandboxHelper() override {} |
| 119 |
| 120 #if defined(OS_WIN) |
| 121 void set_sandbox_info(const sandbox::SandboxInterfaceInfo* info) { |
| 122 sandbox_info_ = info; |
| 123 } |
| 124 #endif |
| 125 |
| 126 #if defined(OS_LINUX) |
| 127 void set_gpu_init(gpu::GpuInit* gpu_init) { gpu_init_ = gpu_init; } |
| 128 #endif |
| 129 |
| 130 private: |
| 131 // SandboxHelper: |
| 132 void PreSandboxStartup() override { |
| 133 // Warm up resources that don't need access to GPUInfo. |
| 134 { |
| 135 TRACE_EVENT0("gpu", "Warm up rand"); |
| 136 // Warm up the random subsystem, which needs to be done pre-sandbox on all |
| 137 // platforms. |
| 138 (void)base::RandUint64(); |
| 139 } |
| 140 |
| 141 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) |
| 142 media::VaapiWrapper::PreSandboxInitialization(); |
| 143 #endif |
| 144 #if defined(OS_WIN) |
| 145 media::DXVAVideoDecodeAccelerator::PreSandboxInitialization(); |
| 146 media::MediaFoundationVideoEncodeAccelerator::PreSandboxInitialization(); |
| 147 #endif |
| 148 } |
| 149 |
| 150 bool EnsureSandboxInitialized() override { |
| 151 #if defined(OS_LINUX) |
| 152 return StartSandboxLinux(gpu_init_->watchdog_thread()); |
| 153 #elif defined(OS_WIN) |
| 154 return StartSandboxWindows(sandbox_info_); |
| 155 #elif defined(OS_MACOSX) |
| 156 return Sandbox::SandboxIsCurrentlyActive(); |
| 157 #else |
| 158 return false; |
| 159 #endif |
| 160 } |
| 161 |
| 162 #if defined(OS_WIN) |
| 163 const sandbox::SandboxInterfaceInfo* sandbox_info_ = nullptr; |
| 164 #elif defined(OS_LINUX) |
| 165 gpu::GpuInit* gpu_init_ = nullptr; |
| 166 #endif |
| 167 |
| 168 DISALLOW_COPY_AND_ASSIGN(ContentSandboxHelper); |
| 169 }; |
| 170 |
| 125 } // namespace anonymous | 171 } // namespace anonymous |
| 126 | 172 |
| 127 // Main function for starting the Gpu process. | 173 // Main function for starting the Gpu process. |
| 128 int GpuMain(const MainFunctionParams& parameters) { | 174 int GpuMain(const MainFunctionParams& parameters) { |
| 129 TRACE_EVENT0("gpu", "GpuMain"); | 175 TRACE_EVENT0("gpu", "GpuMain"); |
| 130 base::trace_event::TraceLog::GetInstance()->SetProcessName("GPU Process"); | 176 base::trace_event::TraceLog::GetInstance()->SetProcessName("GPU Process"); |
| 131 base::trace_event::TraceLog::GetInstance()->SetProcessSortIndex( | 177 base::trace_event::TraceLog::GetInstance()->SetProcessSortIndex( |
| 132 kTraceEventGpuProcessSortIndex); | 178 kTraceEventGpuProcessSortIndex); |
| 133 | 179 |
| 134 const base::CommandLine& command_line = parameters.command_line; | 180 const base::CommandLine& command_line = parameters.command_line; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 152 DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( | 198 DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 153 switches::kWindowDepth)); | 199 switches::kWindowDepth)); |
| 154 DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( | 200 DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 155 switches::kX11VisualID)); | 201 switches::kX11VisualID)); |
| 156 #endif | 202 #endif |
| 157 | 203 |
| 158 #endif | 204 #endif |
| 159 | 205 |
| 160 logging::SetLogMessageHandler(GpuProcessLogMessageHandler); | 206 logging::SetLogMessageHandler(GpuProcessLogMessageHandler); |
| 161 | 207 |
| 162 if (command_line.HasSwitch(switches::kSupportsDualGpus)) { | |
| 163 std::set<int> workarounds; | |
| 164 gpu::GpuDriverBugList::AppendWorkaroundsFromCommandLine(&workarounds, | |
| 165 command_line); | |
| 166 gpu::InitializeDualGpusIfSupported(workarounds); | |
| 167 } | |
| 168 | |
| 169 // Initialization of the OpenGL bindings may fail, in which case we | |
| 170 // will need to tear down this process. However, we can not do so | |
| 171 // safely until the IPC channel is set up, because the detection of | |
| 172 // early return of a child process is implemented using an IPC | |
| 173 // channel error. If the IPC channel is not fully set up between the | |
| 174 // browser and GPU process, and the GPU process crashes or exits | |
| 175 // early, the browser process will never detect it. For this reason | |
| 176 // we defer tearing down the GPU process until receiving the | |
| 177 // GpuMsg_Initialize message from the browser. | |
| 178 bool dead_on_arrival = false; | |
| 179 | |
| 180 #if defined(OS_WIN) | 208 #if defined(OS_WIN) |
| 181 // Use a UI message loop because ANGLE and the desktop GL platform can | 209 // Use a UI message loop because ANGLE and the desktop GL platform can |
| 182 // create child windows to render to. | 210 // create child windows to render to. |
| 183 base::MessagePumpForGpu::InitFactory(); | 211 base::MessagePumpForGpu::InitFactory(); |
| 184 base::MessageLoop main_message_loop(base::MessageLoop::TYPE_UI); | 212 base::MessageLoop main_message_loop(base::MessageLoop::TYPE_UI); |
| 185 #elif defined(OS_LINUX) && defined(USE_X11) | 213 #elif defined(OS_LINUX) && defined(USE_X11) |
| 186 // We need a UI loop so that we can grab the Expose events. See GLSurfaceGLX | 214 // We need a UI loop so that we can grab the Expose events. See GLSurfaceGLX |
| 187 // and https://crbug.com/326995. | 215 // and https://crbug.com/326995. |
| 188 base::MessageLoop main_message_loop(base::MessageLoop::TYPE_UI); | 216 base::MessageLoop main_message_loop(base::MessageLoop::TYPE_UI); |
| 189 std::unique_ptr<ui::PlatformEventSource> event_source = | 217 std::unique_ptr<ui::PlatformEventSource> event_source = |
| 190 ui::PlatformEventSource::CreateDefault(); | 218 ui::PlatformEventSource::CreateDefault(); |
| 191 #elif defined(OS_LINUX) | 219 #elif defined(OS_LINUX) |
| 192 base::MessageLoop main_message_loop(base::MessageLoop::TYPE_DEFAULT); | 220 base::MessageLoop main_message_loop(base::MessageLoop::TYPE_DEFAULT); |
| 193 #elif defined(OS_MACOSX) | 221 #elif defined(OS_MACOSX) |
| 194 // This is necessary for CoreAnimation layers hosted in the GPU process to be | 222 // This is necessary for CoreAnimation layers hosted in the GPU process to be |
| 195 // drawn. See http://crbug.com/312462. | 223 // drawn. See http://crbug.com/312462. |
| 196 std::unique_ptr<base::MessagePump> pump(new base::MessagePumpCFRunLoop()); | 224 std::unique_ptr<base::MessagePump> pump(new base::MessagePumpCFRunLoop()); |
| 197 base::MessageLoop main_message_loop(std::move(pump)); | 225 base::MessageLoop main_message_loop(std::move(pump)); |
| 198 #else | 226 #else |
| 199 base::MessageLoop main_message_loop(base::MessageLoop::TYPE_IO); | 227 base::MessageLoop main_message_loop(base::MessageLoop::TYPE_IO); |
| 200 #endif | 228 #endif |
| 201 | 229 |
| 202 base::PlatformThread::SetName("CrGpuMain"); | 230 base::PlatformThread::SetName("CrGpuMain"); |
| 203 | 231 |
| 204 // In addition to disabling the watchdog if the command line switch is | |
| 205 // present, disable the watchdog on valgrind because the code is expected | |
| 206 // to run slowly in that case. | |
| 207 bool enable_watchdog = | |
| 208 !command_line.HasSwitch(switches::kDisableGpuWatchdog) && | |
| 209 !RunningOnValgrind(); | |
| 210 | |
| 211 // Disable the watchdog in debug builds because they tend to only be run by | |
| 212 // developers who will not appreciate the watchdog killing the GPU process. | |
| 213 #ifndef NDEBUG | |
| 214 enable_watchdog = false; | |
| 215 #endif | |
| 216 | |
| 217 bool delayed_watchdog_enable = false; | |
| 218 | |
| 219 #if defined(OS_CHROMEOS) | |
| 220 // Don't start watchdog immediately, to allow developers to switch to VT2 on | |
| 221 // startup. | |
| 222 delayed_watchdog_enable = true; | |
| 223 #endif | |
| 224 | |
| 225 scoped_refptr<gpu::GpuWatchdogThread> watchdog_thread; | |
| 226 | |
| 227 // Start the GPU watchdog only after anything that is expected to be time | |
| 228 // consuming has completed, otherwise the process is liable to be aborted. | |
| 229 if (enable_watchdog && !delayed_watchdog_enable) | |
| 230 watchdog_thread = gpu::GpuWatchdogThread::Create(); | |
| 231 | |
| 232 // Initializes StatisticsRecorder which tracks UMA histograms. | 232 // Initializes StatisticsRecorder which tracks UMA histograms. |
| 233 base::StatisticsRecorder::Initialize(); | 233 base::StatisticsRecorder::Initialize(); |
| 234 | 234 |
| 235 gpu::GPUInfo gpu_info; | |
| 236 // Get vendor_id, device_id, driver_version from browser process through | |
| 237 // commandline switches. | |
| 238 GetGpuInfoFromCommandLine(gpu_info, command_line); | |
| 239 gpu_info.in_process_gpu = false; | |
| 240 | |
| 241 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) | |
| 242 media::VaapiWrapper::PreSandboxInitialization(); | |
| 243 #endif | |
| 244 | |
| 245 #if defined(OS_ANDROID) || defined(OS_CHROMEOS) | 235 #if defined(OS_ANDROID) || defined(OS_CHROMEOS) |
| 246 // Set thread priority before sandbox initialization. | 236 // Set thread priority before sandbox initialization. |
| 247 base::PlatformThread::SetCurrentThreadPriority(base::ThreadPriority::DISPLAY); | 237 base::PlatformThread::SetCurrentThreadPriority(base::ThreadPriority::DISPLAY); |
| 248 #endif | 238 #endif |
| 249 | 239 |
| 250 // Warm up resources that don't need access to GPUInfo. | 240 gpu::GpuInit gpu_init; |
| 251 WarmUpSandbox(); | 241 ContentSandboxHelper sandbox_helper; |
| 252 | 242 #if defined(OS_WIN) |
| 253 #if defined(OS_LINUX) | 243 sandbox_helper.set_sandbox_info(parameters.sandbox_info); |
| 254 bool initialized_sandbox = false; | 244 #elif defined(OS_LINUX) |
| 255 // On Chrome OS ARM Mali, GPU driver userspace creates threads when | 245 sandbox_helper.set_gpu_init(&gpu_init); |
| 256 // initializing a GL context, so start the sandbox early. | |
| 257 if (command_line.HasSwitch(switches::kGpuSandboxStartEarly)) { | |
| 258 gpu_info.sandboxed = StartSandboxLinux(gpu_info, watchdog_thread.get()); | |
| 259 initialized_sandbox = true; | |
| 260 } | |
| 261 #endif // defined(OS_LINUX) | |
| 262 | |
| 263 base::TimeTicks before_initialize_one_off = base::TimeTicks::Now(); | |
| 264 | |
| 265 // Determine if we need to initialize GL here or it has already been done. | |
| 266 bool gl_already_initialized = false; | |
| 267 #if defined(OS_MACOSX) | |
| 268 if (!command_line.HasSwitch(switches::kNoSandbox)) { | |
| 269 // On Mac, if the sandbox is enabled, then gl::init::InitializeGLOneOff() | |
| 270 // is called from the sandbox warmup code before getting here. | |
| 271 gl_already_initialized = true; | |
| 272 } | |
| 273 #endif | |
| 274 if (command_line.HasSwitch(switches::kInProcessGPU)) { | |
| 275 // With in-process GPU, gl::init::InitializeGLOneOff() is called from | |
| 276 // GpuChildThread before getting here. | |
| 277 gl_already_initialized = true; | |
| 278 } | |
| 279 | |
| 280 // Load and initialize the GL implementation and locate the GL entry points. | |
| 281 bool gl_initialized = | |
| 282 gl_already_initialized | |
| 283 ? gl::GetGLImplementation() != gl::kGLImplementationNone | |
| 284 : gl::init::InitializeGLOneOff(); | |
| 285 if (gl_initialized) { | |
| 286 // We need to collect GL strings (VENDOR, RENDERER) for blacklisting | |
| 287 // purposes. However, on Mac we don't actually use them. As documented in | |
| 288 // crbug.com/222934, due to some driver issues, glGetString could take | |
| 289 // multiple seconds to finish, which in turn cause the GPU process to | |
| 290 // crash. | |
| 291 // By skipping the following code on Mac, we don't really lose anything, | |
| 292 // because the basic GPU information is passed down from browser process | |
| 293 // and we already registered them through SetGpuInfo() above. | |
| 294 base::TimeTicks before_collect_context_graphics_info = | |
| 295 base::TimeTicks::Now(); | |
| 296 #if !defined(OS_MACOSX) | |
| 297 if (!CollectGraphicsInfo(gpu_info)) | |
| 298 dead_on_arrival = true; | |
| 299 | |
| 300 // Recompute gpu driver bug workarounds. | |
| 301 // This is necessary on systems where vendor_id/device_id aren't available | |
| 302 // (Chrome OS, Android) or where workarounds may be dependent on GL_VENDOR | |
| 303 // and GL_RENDERER strings which are lazily computed (Linux). | |
| 304 if (!command_line.HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) { | |
| 305 // TODO: this can not affect disabled extensions, since they're already | |
| 306 // initialized in the bindings. This should be moved before bindings | |
| 307 // initialization. However, populating GPUInfo fully works only on | |
| 308 // Android. Other platforms would need the bindings to query GL strings. | |
| 309 gpu::ApplyGpuDriverBugWorkarounds( | |
| 310 gpu_info, const_cast<base::CommandLine*>(&command_line)); | |
| 311 } | |
| 312 #endif // !defined(OS_MACOSX) | |
| 313 | |
| 314 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | |
| 315 if (gpu_info.gpu.vendor_id == 0x10de && // NVIDIA | |
| 316 gpu_info.driver_vendor == "NVIDIA" && !CanAccessNvidiaDeviceFile()) | |
| 317 dead_on_arrival = true; | |
| 318 #endif // defined(OS_LINUX) && !defined(OS_CHROMEOS) | |
| 319 | |
| 320 base::TimeDelta collect_context_time = | |
| 321 base::TimeTicks::Now() - before_collect_context_graphics_info; | |
| 322 UMA_HISTOGRAM_TIMES("GPU.CollectContextGraphicsInfo", collect_context_time); | |
| 323 } else { // gl_initialized | |
| 324 VLOG(1) << "gl::init::InitializeGLOneOff failed"; | |
| 325 dead_on_arrival = true; | |
| 326 } | |
| 327 | |
| 328 base::TimeDelta initialize_one_off_time = | |
| 329 base::TimeTicks::Now() - before_initialize_one_off; | |
| 330 UMA_HISTOGRAM_MEDIUM_TIMES("GPU.InitializeOneOffMediumTime", | |
| 331 initialize_one_off_time); | |
| 332 if (enable_watchdog && delayed_watchdog_enable) | |
| 333 watchdog_thread = gpu::GpuWatchdogThread::Create(); | |
| 334 | |
| 335 // OSMesa is expected to run very slowly, so disable the watchdog in that | |
| 336 // case. | |
| 337 if (enable_watchdog && | |
| 338 gl::GetGLImplementation() == gl::kGLImplementationOSMesaGL) { | |
| 339 watchdog_thread->Stop(); | |
| 340 watchdog_thread = NULL; | |
| 341 } | |
| 342 | |
| 343 #if defined(OS_LINUX) | |
| 344 if (!initialized_sandbox) | |
| 345 gpu_info.sandboxed = StartSandboxLinux(gpu_info, watchdog_thread.get()); | |
| 346 #elif defined(OS_WIN) | |
| 347 gpu_info.sandboxed = StartSandboxWindows(parameters.sandbox_info); | |
| 348 #elif defined(OS_MACOSX) | |
| 349 gpu_info.sandboxed = Sandbox::SandboxIsCurrentlyActive(); | |
| 350 #endif | 246 #endif |
| 351 | 247 |
| 248 gpu_init.set_sandbox_helper(&sandbox_helper); |
| 249 |
| 250 // Gpu initialization may fail for various reasons, in which case we will need |
| 251 // to tear down this process. However, we can not do so safely until the IPC |
| 252 // channel is set up, because the detection of early return of a child process |
| 253 // is implemented using an IPC channel error. If the IPC channel is not fully |
| 254 // set up between the browser and GPU process, and the GPU process crashes or |
| 255 // exits early, the browser process will never detect it. For this reason we |
| 256 // defer tearing down the GPU process until receiving the GpuMsg_Initialize |
| 257 // message from the browser. |
| 258 const bool init_success = gpu_init.InitializeAndStartSandbox(command_line); |
| 259 const bool dead_on_arrival = !init_success; |
| 260 |
| 352 logging::SetLogMessageHandler(NULL); | 261 logging::SetLogMessageHandler(NULL); |
| 262 GetContentClient()->SetGpuInfo(gpu_init.gpu_info()); |
| 353 | 263 |
| 354 std::unique_ptr<gpu::GpuMemoryBufferFactory> gpu_memory_buffer_factory; | 264 std::unique_ptr<gpu::GpuMemoryBufferFactory> gpu_memory_buffer_factory; |
| 355 if (gpu::GetNativeGpuMemoryBufferType() != gfx::EMPTY_BUFFER) | 265 if (init_success && |
| 266 gpu::GetNativeGpuMemoryBufferType() != gfx::EMPTY_BUFFER) |
| 356 gpu_memory_buffer_factory = gpu::GpuMemoryBufferFactory::CreateNativeType(); | 267 gpu_memory_buffer_factory = gpu::GpuMemoryBufferFactory::CreateNativeType(); |
| 357 | 268 |
| 358 base::ThreadPriority io_thread_priority = base::ThreadPriority::NORMAL; | 269 base::ThreadPriority io_thread_priority = base::ThreadPriority::NORMAL; |
| 359 #if defined(OS_ANDROID) || defined(OS_CHROMEOS) | 270 #if defined(OS_ANDROID) || defined(OS_CHROMEOS) |
| 360 io_thread_priority = base::ThreadPriority::DISPLAY; | 271 io_thread_priority = base::ThreadPriority::DISPLAY; |
| 361 #endif | 272 #endif |
| 362 | 273 |
| 363 GpuProcess gpu_process(io_thread_priority); | 274 GpuProcess gpu_process(io_thread_priority); |
| 364 | |
| 365 GpuChildThread* child_thread = new GpuChildThread( | 275 GpuChildThread* child_thread = new GpuChildThread( |
| 366 watchdog_thread.get(), dead_on_arrival, gpu_info, deferred_messages.Get(), | 276 gpu_init.watchdog_thread(), dead_on_arrival, gpu_init.gpu_info(), |
| 367 gpu_memory_buffer_factory.get()); | 277 deferred_messages.Get(), gpu_memory_buffer_factory.get()); |
| 368 while (!deferred_messages.Get().empty()) | 278 while (!deferred_messages.Get().empty()) |
| 369 deferred_messages.Get().pop(); | 279 deferred_messages.Get().pop(); |
| 370 | 280 |
| 371 child_thread->Init(start_time); | 281 child_thread->Init(start_time); |
| 372 | 282 |
| 373 gpu_process.set_main_thread(child_thread); | 283 gpu_process.set_main_thread(child_thread); |
| 374 | 284 |
| 375 if (watchdog_thread.get()) | 285 if (gpu_init.watchdog_thread()) |
| 376 watchdog_thread->AddPowerObserver(); | 286 gpu_init.watchdog_thread()->AddPowerObserver(); |
| 377 | 287 |
| 378 #if defined(OS_ANDROID) | 288 #if defined(OS_ANDROID) |
| 379 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( | 289 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( |
| 380 tracing::GraphicsMemoryDumpProvider::GetInstance(), "AndroidGraphics", | 290 tracing::GraphicsMemoryDumpProvider::GetInstance(), "AndroidGraphics", |
| 381 nullptr); | 291 nullptr); |
| 382 #endif | 292 #endif |
| 383 | 293 |
| 384 { | 294 { |
| 385 TRACE_EVENT0("gpu", "Run Message Loop"); | 295 TRACE_EVENT0("gpu", "Run Message Loop"); |
| 386 base::RunLoop().Run(); | 296 base::RunLoop().Run(); |
| 387 } | 297 } |
| 388 | 298 |
| 389 child_thread->StopWatchdog(); | 299 child_thread->StopWatchdog(); |
| 390 | 300 |
| 391 return dead_on_arrival ? 2 : 0; | 301 return dead_on_arrival ? 2 : 0; |
| 392 } | 302 } |
| 393 | 303 |
| 394 namespace { | 304 namespace { |
| 395 | 305 |
| 396 void GetGpuInfoFromCommandLine(gpu::GPUInfo& gpu_info, | |
| 397 const base::CommandLine& command_line) { | |
| 398 DCHECK(command_line.HasSwitch(switches::kGpuVendorID) && | |
| 399 command_line.HasSwitch(switches::kGpuDeviceID) && | |
| 400 command_line.HasSwitch(switches::kGpuDriverVersion)); | |
| 401 bool success = base::HexStringToUInt( | |
| 402 command_line.GetSwitchValueASCII(switches::kGpuVendorID), | |
| 403 &gpu_info.gpu.vendor_id); | |
| 404 DCHECK(success); | |
| 405 success = base::HexStringToUInt( | |
| 406 command_line.GetSwitchValueASCII(switches::kGpuDeviceID), | |
| 407 &gpu_info.gpu.device_id); | |
| 408 DCHECK(success); | |
| 409 gpu_info.driver_vendor = | |
| 410 command_line.GetSwitchValueASCII(switches::kGpuDriverVendor); | |
| 411 gpu_info.driver_version = | |
| 412 command_line.GetSwitchValueASCII(switches::kGpuDriverVersion); | |
| 413 gpu_info.driver_date = | |
| 414 command_line.GetSwitchValueASCII(switches::kGpuDriverDate); | |
| 415 gpu::ParseSecondaryGpuDevicesFromCommandLine(command_line, &gpu_info); | |
| 416 | |
| 417 // Set active gpu device. | |
| 418 if (command_line.HasSwitch(switches::kGpuActiveVendorID) && | |
| 419 command_line.HasSwitch(switches::kGpuActiveDeviceID)) { | |
| 420 uint32_t active_vendor_id = 0; | |
| 421 uint32_t active_device_id = 0; | |
| 422 success = base::HexStringToUInt( | |
| 423 command_line.GetSwitchValueASCII(switches::kGpuActiveVendorID), | |
| 424 &active_vendor_id); | |
| 425 DCHECK(success); | |
| 426 success = base::HexStringToUInt( | |
| 427 command_line.GetSwitchValueASCII(switches::kGpuActiveDeviceID), | |
| 428 &active_device_id); | |
| 429 DCHECK(success); | |
| 430 if (gpu_info.gpu.vendor_id == active_vendor_id && | |
| 431 gpu_info.gpu.device_id == active_device_id) { | |
| 432 gpu_info.gpu.active = true; | |
| 433 } else { | |
| 434 for (size_t i = 0; i < gpu_info.secondary_gpus.size(); ++i) { | |
| 435 if (gpu_info.secondary_gpus[i].vendor_id == active_vendor_id && | |
| 436 gpu_info.secondary_gpus[i].device_id == active_device_id) { | |
| 437 gpu_info.secondary_gpus[i].active = true; | |
| 438 break; | |
| 439 } | |
| 440 } | |
| 441 } | |
| 442 } | |
| 443 | |
| 444 GetContentClient()->SetGpuInfo(gpu_info); | |
| 445 } | |
| 446 | |
| 447 void WarmUpSandbox() { | |
| 448 { | |
| 449 TRACE_EVENT0("gpu", "Warm up rand"); | |
| 450 // Warm up the random subsystem, which needs to be done pre-sandbox on all | |
| 451 // platforms. | |
| 452 (void) base::RandUint64(); | |
| 453 } | |
| 454 | |
| 455 #if defined(OS_WIN) | |
| 456 media::DXVAVideoDecodeAccelerator::PreSandboxInitialization(); | |
| 457 media::MediaFoundationVideoEncodeAccelerator::PreSandboxInitialization(); | |
| 458 #endif | |
| 459 } | |
| 460 | |
| 461 #if !defined(OS_MACOSX) | |
| 462 bool CollectGraphicsInfo(gpu::GPUInfo& gpu_info) { | |
| 463 TRACE_EVENT0("gpu,startup", "Collect Graphics Info"); | |
| 464 | |
| 465 bool res = true; | |
| 466 gpu::CollectInfoResult result = gpu::CollectContextGraphicsInfo(&gpu_info); | |
| 467 switch (result) { | |
| 468 case gpu::kCollectInfoFatalFailure: | |
| 469 LOG(ERROR) << "gpu::CollectGraphicsInfo failed (fatal)."; | |
| 470 res = false; | |
| 471 break; | |
| 472 case gpu::kCollectInfoNonFatalFailure: | |
| 473 DVLOG(1) << "gpu::CollectGraphicsInfo failed (non-fatal)."; | |
| 474 break; | |
| 475 case gpu::kCollectInfoNone: | |
| 476 NOTREACHED(); | |
| 477 break; | |
| 478 case gpu::kCollectInfoSuccess: | |
| 479 break; | |
| 480 } | |
| 481 GetContentClient()->SetGpuInfo(gpu_info); | |
| 482 return res; | |
| 483 } | |
| 484 #endif | |
| 485 | |
| 486 #if defined(OS_LINUX) | 306 #if defined(OS_LINUX) |
| 487 #if !defined(OS_CHROMEOS) | 307 bool StartSandboxLinux(gpu::GpuWatchdogThread* watchdog_thread) { |
| 488 bool CanAccessNvidiaDeviceFile() { | |
| 489 bool res = true; | |
| 490 base::ThreadRestrictions::AssertIOAllowed(); | |
| 491 if (access("/dev/nvidiactl", R_OK) != 0) { | |
| 492 DVLOG(1) << "NVIDIA device file /dev/nvidiactl access denied"; | |
| 493 res = false; | |
| 494 } | |
| 495 return res; | |
| 496 } | |
| 497 #endif | |
| 498 | |
| 499 bool StartSandboxLinux(const gpu::GPUInfo& gpu_info, | |
| 500 gpu::GpuWatchdogThread* watchdog_thread) { | |
| 501 TRACE_EVENT0("gpu,startup", "Initialize sandbox"); | 308 TRACE_EVENT0("gpu,startup", "Initialize sandbox"); |
| 502 | 309 |
| 503 bool res = false; | 310 bool res = false; |
| 504 | 311 |
| 505 if (watchdog_thread) { | 312 if (watchdog_thread) { |
| 506 // LinuxSandbox needs to be able to ensure that the thread | 313 // LinuxSandbox needs to be able to ensure that the thread |
| 507 // has really been stopped. | 314 // has really been stopped. |
| 508 LinuxSandbox::StopThread(watchdog_thread); | 315 LinuxSandbox::StopThread(watchdog_thread); |
| 509 } | 316 } |
| 510 | 317 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 544 return true; | 351 return true; |
| 545 } | 352 } |
| 546 | 353 |
| 547 return false; | 354 return false; |
| 548 } | 355 } |
| 549 #endif // defined(OS_WIN) | 356 #endif // defined(OS_WIN) |
| 550 | 357 |
| 551 } // namespace. | 358 } // namespace. |
| 552 | 359 |
| 553 } // namespace content | 360 } // namespace content |
| OLD | NEW |