| Index: chrome/gpu/gpu_thread.cc
|
| ===================================================================
|
| --- chrome/gpu/gpu_thread.cc (revision 70570)
|
| +++ chrome/gpu/gpu_thread.cc (working copy)
|
| @@ -8,41 +8,49 @@
|
| #include <vector>
|
|
|
| #include "app/gfx/gl/gl_context.h"
|
| +#include "app/gfx/gl/gl_implementation.h"
|
| #include "app/win/scoped_com_initializer.h"
|
| #include "base/command_line.h"
|
| #include "base/threading/worker_pool.h"
|
| #include "build/build_config.h"
|
| #include "chrome/common/child_process.h"
|
| #include "chrome/common/child_process_logging.h"
|
| +#include "chrome/common/chrome_switches.h"
|
| #include "chrome/common/gpu_messages.h"
|
| #include "chrome/gpu/gpu_info_collector.h"
|
| +#include "chrome/gpu/gpu_watchdog_thread.h"
|
| #include "ipc/ipc_channel_handle.h"
|
|
|
| -GpuThread::GpuThread() {
|
| +#if defined(OS_MACOSX)
|
| +#include "chrome/common/sandbox_mac.h"
|
| +#endif
|
| +
|
| +const int kGpuTimeout = 10000;
|
| +
|
| +namespace {
|
| +
|
| +bool InitializeGpuSandbox() {
|
| +#if defined(OS_MACOSX)
|
| + CommandLine* parsed_command_line = CommandLine::ForCurrentProcess();
|
| + SandboxInitWrapper sandbox_wrapper;
|
| + return sandbox_wrapper.InitializeSandbox(*parsed_command_line,
|
| + switches::kGpuProcess);
|
| +#else
|
| + // TODO(port): Create GPU sandbox for linux and windows.
|
| + return true;
|
| +#endif
|
| }
|
|
|
| +} // namespace
|
| +
|
| +GpuThread::GpuThread(const CommandLine& command_line)
|
| + : command_line_(command_line) {}
|
| +
|
| GpuThread::~GpuThread() {
|
| }
|
|
|
| void GpuThread::Init(const base::Time& process_start_time) {
|
| - gpu_info_collector::CollectGraphicsInfo(&gpu_info_);
|
| - child_process_logging::SetGpuInfo(gpu_info_);
|
| -
|
| -#if defined(OS_WIN)
|
| - // Asynchronously collect the DirectX diagnostics because this can take a
|
| - // couple of seconds.
|
| - if (!base::WorkerPool::PostTask(
|
| - FROM_HERE,
|
| - NewRunnableFunction(&GpuThread::CollectDxDiagnostics, this),
|
| - true)) {
|
| - // Flag GPU info as complete if the DirectX diagnostics cannot be collected.
|
| - gpu_info_.SetProgress(GPUInfo::kComplete);
|
| - }
|
| -#endif
|
| -
|
| - // Record initialization only after collecting the GPU info because that can
|
| - // take a significant amount of time.
|
| - gpu_info_.SetInitializationTime(base::Time::Now() - process_start_time);
|
| + process_start_time_ = process_start_time;
|
| }
|
|
|
| void GpuThread::RemoveChannel(int renderer_id) {
|
| @@ -53,6 +61,7 @@
|
| bool msg_is_ok = true;
|
| bool handled = true;
|
| IPC_BEGIN_MESSAGE_MAP_EX(GpuThread, msg, msg_is_ok)
|
| + IPC_MESSAGE_HANDLER(GpuMsg_Initialize, OnInitialize)
|
| IPC_MESSAGE_HANDLER(GpuMsg_EstablishChannel, OnEstablishChannel)
|
| IPC_MESSAGE_HANDLER(GpuMsg_CloseChannel, OnCloseChannel)
|
| IPC_MESSAGE_HANDLER(GpuMsg_Synchronize, OnSynchronize)
|
| @@ -70,6 +79,83 @@
|
| return handled;
|
| }
|
|
|
| +void GpuThread::OnInitialize() {
|
| + // Load the GL implementation and locate the bindings before starting the GPU
|
| + // watchdog because this can take a lot of time and the GPU watchdog might
|
| + // terminate the GPU process.
|
| + if (!gfx::GLContext::InitializeOneOff()) {
|
| + MessageLoop::current()->Quit();
|
| + return;
|
| + }
|
| + gpu_info_collector::CollectGraphicsInfo(&gpu_info_);
|
| + child_process_logging::SetGpuInfo(gpu_info_);
|
| +
|
| +#if defined(OS_WIN)
|
| + // Asynchronously collect the DirectX diagnostics because this can take a
|
| + // couple of seconds.
|
| + if (!base::WorkerPool::PostTask(
|
| + FROM_HERE,
|
| + NewRunnableFunction(&GpuThread::CollectDxDiagnostics, this),
|
| + true)) {
|
| + // Flag GPU info as complete if the DirectX diagnostics cannot be collected.
|
| + gpu_info_.SetProgress(GPUInfo::kComplete);
|
| + }
|
| +#endif
|
| +
|
| + // Record initialization only after collecting the GPU info because that can
|
| + // take a significant amount of time.
|
| + gpu_info_.SetInitializationTime(base::Time::Now() - process_start_time_);
|
| +
|
| + // Note that kNoSandbox will also disable the GPU sandbox.
|
| + bool no_gpu_sandbox = command_line_.HasSwitch(switches::kNoGpuSandbox);
|
| + if (!no_gpu_sandbox) {
|
| + if (!InitializeGpuSandbox()) {
|
| + LOG(ERROR) << "Failed to initialize the GPU sandbox";
|
| + MessageLoop::current()->Quit();
|
| + return;
|
| + }
|
| + } else {
|
| + LOG(ERROR) << "Running without GPU sandbox";
|
| + }
|
| +
|
| + // In addition to disabling the watchdog if the command line switch is
|
| + // present, disable it in two other cases. OSMesa is expected to run very
|
| + // slowly. Also disable the watchdog on valgrind because the code is expected
|
| + // to run slowly in that case.
|
| + bool enable_watchdog =
|
| + !command_line_.HasSwitch(switches::kDisableGpuWatchdog) &&
|
| + gfx::GetGLImplementation() != gfx::kGLImplementationOSMesaGL &&
|
| + !RunningOnValgrind();
|
| +
|
| + // Disable the watchdog in debug builds because they tend to only be run by
|
| + // developers who will not appreciate the watchdog killing the GPU process.
|
| +#ifndef NDEBUG
|
| + enable_watchdog = false;
|
| +#endif
|
| +
|
| + // Disable the watchdog for Windows. It tends to abort when the GPU process
|
| + // is not hung but still taking a long time to do something. Instead, the
|
| + // browser process displays a dialog when it notices that the child window
|
| + // is hung giving the user an opportunity to terminate it. This is the
|
| + // same mechanism used to abort hung plugins.
|
| +#if defined(OS_WIN)
|
| + enable_watchdog = false;
|
| +#endif
|
| +
|
| + // Start the GPU watchdog only after anything that is expected to be time
|
| + // consuming has completed, otherwise the process is liable to be aborted.
|
| + if (enable_watchdog) {
|
| + watchdog_thread_ = new GpuWatchdogThread(kGpuTimeout);
|
| + watchdog_thread_->Start();
|
| + }
|
| +}
|
| +
|
| +void GpuThread::StopWatchdog() {
|
| + if (watchdog_thread_.get()) {
|
| + watchdog_thread_->Stop();
|
| + }
|
| +}
|
| +
|
| void GpuThread::OnEstablishChannel(int renderer_id) {
|
| scoped_refptr<GpuChannel> channel;
|
| IPC::ChannelHandle channel_handle;
|
|
|