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 "content/browser/gpu/gpu_process_host.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/base64.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_switches.h"
9424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/basictypes.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
11424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/callback_helpers.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/sha1.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/browser_child_process_host_impl.h"
20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/gpu/compositor_util.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/gpu/gpu_data_manager_impl.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/gpu/gpu_process_host_ui_shim.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/gpu/shader_disk_cache.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/render_widget_host_impl.h"
25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/renderer_host/render_widget_resize_helper.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/child_process_host_impl.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/gpu_messages.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/view_messages.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/content_browser_client.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_widget_host_view.h"
33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/content_client.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/content_switches.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/result_codes.h"
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/public/common/sandboxed_process_launcher_delegate.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/gpu_switches.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_channel_handle.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_switches.h"
415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ipc/message_filter.h"
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "media/base/media_switches.h"
436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "ui/base/ui_base_switches.h"
4468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/events/latency_info.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_switches.h"
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/win/windows_version.h"
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/common/sandbox_win.h"
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sandbox/win/src/sandbox_policy.h"
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/switches.h"
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(USE_OZONE)
55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "ui/ozone/public/ozone_switches.h"
56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif
57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(USE_X11) && !defined(OS_CHROMEOS)
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/gfx/x/x11_switches.h"
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuProcessHost::gpu_enabled_ = true;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuProcessHost::hardware_gpu_enabled_ = true;
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int GpuProcessHost::gpu_crash_count_ = 0;
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int GpuProcessHost::gpu_recent_crash_count_ = 0;
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool GpuProcessHost::crashed_before_ = false;
695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int GpuProcessHost::swiftshader_crash_count_ = 0;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Command-line switches to propagate to the GPU process.
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistatic const char* const kSwitchNames[] = {
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kDisableAcceleratedVideoDecode,
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kDisableBreakpad,
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kDisableGpuSandbox,
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kDisableGpuWatchdog,
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kDisableLogging,
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kDisableSeccompFilterSandbox,
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(ENABLE_WEBRTC)
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kDisableWebRtcHWEncoding,
8334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  switches::kEnableWebRtcHWVp8Encoding,
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kEnableLogging,
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kEnableShareGroupAsyncTextureUpload,
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_CHROMEOS)
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kDisableVaapiAcceleratedVideoEncode,
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kGpuStartupDialog,
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kGpuSandboxAllowSysVShm,
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kGpuSandboxFailuresFatal,
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kGpuSandboxStartEarly,
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kIgnoreResolutionLimitsForAcceleratedVideoDecode,
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kLoggingLevel,
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kLowEndDeviceMode,
971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kNoSandbox,
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kTestGLLib,
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kTraceStartup,
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kTraceToConsole,
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kV,
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kVModule,
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_MACOSX)
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kEnableRemoteCoreAnimation,
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kEnableSandboxLogging,
1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(USE_AURA)
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kUIPrioritizeInGpuProcess,
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(USE_OZONE)
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kOzonePlatform,
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kOzoneUseSurfaceless,
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(USE_X11) && !defined(OS_CHROMEOS)
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switches::kX11Display,
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum GPUProcessLifetimeEvent {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LAUNCHED,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DIED_FIRST_TIME,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DIED_SECOND_TIME,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DIED_THIRD_TIME,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DIED_FOURTH_TIME,
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GPU_PROCESS_LIFETIME_EVENT_MAX = 100
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Indexed by GpuProcessKind. There is one of each kind maximum. This array may
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// only be accessed from the IO thread.
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)GpuProcessHost* g_gpu_process_hosts[GpuProcessHost::GPU_PROCESS_KIND_COUNT];
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SendGpuProcessMessage(GpuProcessHost::GpuProcessKind kind,
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           CauseForGpuLaunch cause,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           IPC::Message* message) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GpuProcessHost* host = GpuProcessHost::Get(kind, cause);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host->Send(message);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete message;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// NOTE: changes to this class need to be reviewed by the security team.
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class GpuSandboxedProcessLauncherDelegate
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public SandboxedProcessLauncherDelegate {
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
1486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  GpuSandboxedProcessLauncherDelegate(base::CommandLine* cmd_line,
149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                      ChildProcessHost* host)
150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(OS_WIN)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : cmd_line_(cmd_line) {}
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#elif defined(OS_POSIX)
153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      : ipc_fd_(host->TakeClientFileDescriptor()) {}
154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif
155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~GpuSandboxedProcessLauncherDelegate() {}
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(OS_WIN)
159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual bool ShouldSandbox() OVERRIDE {
160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    bool sandbox = !cmd_line_->HasSwitch(switches::kDisableGpuSandbox);
161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if(! sandbox) {
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DVLOG(1) << "GPU sandbox is disabled";
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return sandbox;
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void PreSandbox(bool* disable_default_policy,
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          base::FilePath* exposed_dir) OVERRIDE {
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *disable_default_policy = true;
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // For the GPU process we gotten as far as USER_LIMITED. The next level
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // which is USER_RESTRICTED breaks both the DirectX backend and the OpenGL
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // backend. Note that the GPU process is connected to the interactive
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // desktop.
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void PreSpawnTarget(sandbox::TargetPolicy* policy,
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              bool* success) {
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (base::win::GetVersion() > base::win::VERSION_XP) {
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (cmd_line_->GetSwitchValueASCII(switches::kUseGL) ==
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          gfx::kGLImplementationDesktopName) {
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // Open GL path.
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              sandbox::USER_LIMITED);
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SetJobLevel(*cmd_line_, sandbox::JOB_UNPROTECTED, 0, policy);
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                              sandbox::USER_LIMITED);
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // UI restrictions break when we access Windows from outside our job.
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // However, we don't want a proxy window in this process because it can
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // introduce deadlocks where the renderer blocks on the gpu, which in
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // turn blocks on the browser UI thread. So, instead we forgo a window
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // message pump entirely and just add job restrictions to prevent child
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // processes.
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SetJobLevel(*cmd_line_,
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    sandbox::JOB_LIMITED_USER,
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS |
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    JOB_OBJECT_UILIMIT_DESKTOP |
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    JOB_OBJECT_UILIMIT_EXITWINDOWS |
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    JOB_OBJECT_UILIMIT_DISPLAYSETTINGS,
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    policy);
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        policy->SetIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SetJobLevel(*cmd_line_, sandbox::JOB_UNPROTECTED, 0, policy);
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      policy->SetTokenLevel(sandbox::USER_UNPROTECTED,
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            sandbox::USER_LIMITED);
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Allow the server side of GPU sockets, which are pipes that have
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // the "chrome.gpu" namespace and an arbitrary suffix.
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sandbox::ResultCode result = policy->AddRule(
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        sandbox::TargetPolicy::SUBSYS_NAMED_PIPES,
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        sandbox::TargetPolicy::NAMEDPIPES_ALLOW_ANY,
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        L"\\\\.\\pipe\\chrome.gpu.*");
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (result != sandbox::SBOX_ALL_OK) {
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *success = false;
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Block this DLL even if it is not loaded by the browser process.
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    policy->AddDllToUnload(L"cmsetac.dll");
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifdef USE_AURA
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // GPU also needs to add sections to the browser for aura
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TODO(jschuh): refactor the GPU channel to remove this. crbug.com/128786
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES,
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             sandbox::TargetPolicy::HANDLES_DUP_BROKER,
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             L"Section");
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (result != sandbox::SBOX_ALL_OK) {
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *success = false;
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (cmd_line_->HasSwitch(switches::kEnableLogging)) {
239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::string16 log_file_path = logging::GetLogFileFullPath();
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!log_file_path.empty()) {
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 sandbox::TargetPolicy::FILES_ALLOW_ANY,
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 log_file_path.c_str());
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (result != sandbox::SBOX_ALL_OK) {
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          *success = false;
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          return;
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#elif defined(OS_POSIX)
252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual int GetIpcFd() OVERRIDE {
254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return ipc_fd_;
255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif  // OS_WIN
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(OS_WIN)
2606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::CommandLine* cmd_line_;
261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#elif defined(OS_POSIX)
262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int ipc_fd_;
263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif  // OS_WIN
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // anonymous namespace
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GpuProcessHost::ValidateHost(GpuProcessHost* host) {
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The Gpu process is invalid if it's not using SwiftShader, the card is
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // blacklisted, and we can kill it and start over.
2726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          switches::kSingleProcess) ||
2746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      base::CommandLine::ForCurrentProcess()->HasSwitch(
2756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          switches::kInProcessGPU) ||
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (host->valid_ &&
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       (host->swiftshader_rendering_ ||
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        !GpuDataManagerImpl::GetInstance()->ShouldUseSwiftShader()))) {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  host->ForceShutdown();
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuProcessHost* GpuProcessHost::Get(GpuProcessKind kind,
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    CauseForGpuLaunch cause) {
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't grant further access to GPU if it is not allowed.
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance();
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(gpu_data_manager);
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!gpu_data_manager->GpuAccessAllowed(NULL))
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (g_gpu_process_hosts[kind] && ValidateHost(g_gpu_process_hosts[kind]))
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return g_gpu_process_hosts[kind];
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cause == CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static int last_host_id = 0;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int host_id;
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  host_id = ++last_host_id;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLaunchCause",
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            cause,
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            CAUSE_FOR_GPU_LAUNCH_MAX_ENUM);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GpuProcessHost* host = new GpuProcessHost(host_id, kind);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host->Init())
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return host;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete host;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuProcessHost::GetProcessHandles(
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GpuDataManager::GetGpuProcessHandlesCallback& callback)  {
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BrowserThread::PostTask(
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        BrowserThread::IO,
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&GpuProcessHost::GetProcessHandles, callback));
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::list<base::ProcessHandle> handles;
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < arraysize(g_gpu_process_hosts); ++i) {
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GpuProcessHost* host = g_gpu_process_hosts[i];
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (host && ValidateHost(host))
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      handles.push_back(host->process_->GetHandle());
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BrowserThread::PostTask(
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      BrowserThread::UI,
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(callback, handles));
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuProcessHost::SendOnIO(GpuProcessKind kind,
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              CauseForGpuLaunch cause,
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              IPC::Message* message) {
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!BrowserThread::PostTask(
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          BrowserThread::IO, FROM_HERE,
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              &SendGpuProcessMessage, kind, cause, message))) {
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete message;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)GpuMainThreadFactoryFunction g_gpu_main_thread_factory = NULL;
3543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void GpuProcessHost::RegisterGpuMainThreadFactory(
3563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    GpuMainThreadFactoryFunction create) {
3573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  g_gpu_main_thread_factory = create;
3583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuProcessHost* GpuProcessHost::FromID(int host_id) {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < GPU_PROCESS_KIND_COUNT; ++i) {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GpuProcessHost* host = g_gpu_process_hosts[i];
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (host && host->host_id_ == host_id && ValidateHost(host))
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return host;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuProcessHost::GpuProcessHost(int host_id, GpuProcessKind kind)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : host_id_(host_id),
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      valid_(true),
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      in_process_(false),
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      swiftshader_rendering_(false),
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kind_(kind),
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      process_launched_(false),
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      initialized_(false),
3815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      gpu_crash_recorded_(false),
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      uma_memory_stats_received_(false) {
3836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
3846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          switches::kSingleProcess) ||
3856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      base::CommandLine::ForCurrentProcess()->HasSwitch(
3866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          switches::kInProcessGPU)) {
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    in_process_ = true;
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the 'single GPU process' policy ever changes, we still want to maintain
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it for 'gpu thread' mode and only create one instance of host and thread.
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!in_process_ || g_gpu_process_hosts[kind] == NULL);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_gpu_process_hosts[kind] = this;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Post a task to create the corresponding GpuProcessHostUIShim.  The
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GpuProcessHostUIShim will be destroyed if either the browser exits,
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in which case it calls GpuProcessHostUIShim::DestroyAll, or the
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GpuProcessHost is destroyed, which happens when the corresponding GPU
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // process terminates or fails to launch.
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::UI,
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(base::IgnoreResult(&GpuProcessHostUIShim::Create), host_id));
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process_.reset(new BrowserChildProcessHostImpl(PROCESS_TYPE_GPU, this));
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuProcessHost::~GpuProcessHost() {
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendOutstandingReplies();
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  RecordProcessCrash();
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // In case we never started, clean up.
417868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  while (!queued_messages_.empty()) {
418868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    delete queued_messages_.front();
419868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    queued_messages_.pop();
420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
421868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // This is only called on the IO thread so no race against the constructor
423868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // for another GpuProcessHost.
424868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (g_gpu_process_hosts[kind_] == this)
425868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    g_gpu_process_hosts[kind_] = NULL;
426868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
427868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // If there are any remaining offscreen contexts at the point the
428868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // GPU process exits, assume something went wrong, and block their
429868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // URLs from accessing client 3D APIs without prompting.
430868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  BlockLiveOffscreenContexts();
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UMA_HISTOGRAM_COUNTS_100("GPU.AtExitSurfaceCount",
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           GpuSurfaceTracker::Get()->GetSurfaceCount());
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UMA_HISTOGRAM_BOOLEAN("GPU.AtExitReceivedMemoryStats",
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        uma_memory_stats_received_);
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (uma_memory_stats_received_) {
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UMA_HISTOGRAM_COUNTS_100("GPU.AtExitManagedMemoryClientCount",
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             uma_memory_stats_.client_count);
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UMA_HISTOGRAM_COUNTS_100("GPU.AtExitContextGroupCount",
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             uma_memory_stats_.context_group_count);
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UMA_HISTOGRAM_CUSTOM_COUNTS(
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "GPU.AtExitMBytesAllocated",
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        uma_memory_stats_.bytes_allocated_current / 1024 / 1024, 1, 2000, 50);
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UMA_HISTOGRAM_CUSTOM_COUNTS(
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "GPU.AtExitMBytesAllocatedMax",
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        uma_memory_stats_.bytes_allocated_max / 1024 / 1024, 1, 2000, 50);
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UMA_HISTOGRAM_CUSTOM_COUNTS(
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "GPU.AtExitMBytesLimit",
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        uma_memory_stats_.bytes_limit / 1024 / 1024, 1, 2000, 50);
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string message;
454868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!in_process_) {
455868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int exit_code;
456424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    base::TerminationStatus status = process_->GetTerminationStatus(
457424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        false /* known_dead */, &exit_code);
458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessTerminationStatus",
459868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              status,
460868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              base::TERMINATION_STATUS_MAX_ENUM);
461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
462868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (status == base::TERMINATION_STATUS_NORMAL_TERMINATION ||
463868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION) {
464868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessExitCode",
465868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                exit_code,
466868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                RESULT_CODE_LAST_CODE);
467868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
468868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
469868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    switch (status) {
470868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      case base::TERMINATION_STATUS_NORMAL_TERMINATION:
471868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        message = "The GPU process exited normally. Everything is okay.";
472868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        break;
473868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
474868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        message = base::StringPrintf(
475868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            "The GPU process exited with code %d.",
476868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            exit_code);
477868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        break;
478868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
479868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        message = "You killed the GPU process! Why?";
480868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        break;
481868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      case base::TERMINATION_STATUS_PROCESS_CRASHED:
482868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        message = "The GPU process crashed!";
483868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        break;
484868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      default:
485868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        break;
486868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::UI,
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          FROM_HERE,
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          base::Bind(&GpuProcessHostUIShim::Destroy,
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     host_id_,
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     message));
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuProcessHost::Init() {
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_start_time_ = base::TimeTicks::Now();
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TRACE_EVENT_INSTANT0("gpu", "LaunchGpuProcess", TRACE_EVENT_SCOPE_THREAD);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string channel_id = process_->GetHost()->CreateChannel();
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (channel_id.empty())
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (in_process_) {
506f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(g_gpu_main_thread_factory);
5076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    command_line->AppendSwitch(switches::kDisableGpuWatchdog);
5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance();
5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(gpu_data_manager);
5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gpu_data_manager->AppendGpuCommandLine(command_line);
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    in_process_gpu_thread_.reset(g_gpu_main_thread_factory(channel_id));
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    in_process_gpu_thread_->Start();
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnProcessLaunched();  // Fake a callback that the process is ready.
5183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else if (!LaunchGpuProcess(channel_id)) {
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Send(new GpuMsg_Initialize()))
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuProcessHost::RouteOnUIThread(const IPC::Message& message) {
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::UI,
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&RouteToGpuProcessHostUIShimTask, host_id_, message));
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuProcessHost::Send(IPC::Message* msg) {
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (process_->GetHost()->IsChannelOpening()) {
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    queued_messages_.push(msg);
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool result = process_->Send(msg);
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!result) {
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Channel is hosed, but we may not get destroyed for a while. Send
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // outstanding channel creation failures now so that the caller can restart
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // with a new process/channel without waiting.
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SendOutstandingReplies();
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid GpuProcessHost::AddFilter(IPC::MessageFilter* filter) {
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process_->GetHost()->AddFilter(filter);
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuProcessHost::OnMessageReceived(const IPC::Message& message) {
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(GpuProcessHost, message)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuHostMsg_Initialized, OnInitialized)
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuHostMsg_ChannelEstablished, OnChannelEstablished)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuHostMsg_CommandBufferCreated, OnCommandBufferCreated)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuHostMsg_DestroyCommandBuffer, OnDestroyCommandBuffer)
564f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuHostMsg_GpuMemoryBufferCreated,
565f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        OnGpuMemoryBufferCreated)
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuHostMsg_DidCreateOffscreenContext,
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        OnDidCreateOffscreenContext)
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuHostMsg_DidLoseContext, OnDidLoseContext)
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuHostMsg_DidDestroyOffscreenContext,
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        OnDidDestroyOffscreenContext)
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuHostMsg_GpuMemoryUmaStats,
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        OnGpuMemoryUmaStatsReceived)
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
574116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    IPC_MESSAGE_HANDLER_GENERIC(GpuHostMsg_AcceleratedSurfaceBuffersSwapped,
575116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                OnAcceleratedSurfaceBuffersSwapped(message))
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuHostMsg_DestroyChannel,
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        OnDestroyChannel)
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuHostMsg_CacheShader,
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        OnCacheShader)
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_UNHANDLED(RouteOnUIThread(message))
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_END_MESSAGE_MAP()
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuProcessHost::OnChannelConnected(int32 peer_pid) {
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT0("gpu", "GpuProcessHost::OnChannelConnected");
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!queued_messages_.empty()) {
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(queued_messages_.front());
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    queued_messages_.pop();
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuProcessHost::EstablishGpuChannel(
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int client_id,
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool share_context,
600116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    bool allow_future_sync_points,
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EstablishChannelCallback& callback) {
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT0("gpu", "GpuProcessHost::EstablishGpuChannel");
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If GPU features are already blacklisted, no need to establish the channel.
606c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!GpuDataManagerImpl::GetInstance()->GpuAccessAllowed(NULL)) {
607a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DVLOG(1) << "GPU blacklisted, refusing to open a GPU channel.";
60890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    callback.Run(IPC::ChannelHandle(), gpu::GPUInfo());
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
612116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (Send(new GpuMsg_EstablishChannel(
613116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          client_id, share_context, allow_future_sync_points))) {
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel_requests_.push(callback);
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
616a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DVLOG(1) << "Failed to send GpuMsg_EstablishChannel.";
61790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    callback.Run(IPC::ChannelHandle(), gpu::GPUInfo());
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      switches::kDisableGpuShaderDiskCache)) {
6227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    CreateChannelCache(client_id);
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuProcessHost::CreateViewCommandBuffer(
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::GLSurfaceHandle& compositing_surface,
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int surface_id,
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int client_id,
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GPUCreateCommandBufferConfig& init_params,
631c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    int route_id,
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const CreateCommandBufferCallback& callback) {
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT0("gpu", "GpuProcessHost::CreateViewCommandBuffer");
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!compositing_surface.is_null() &&
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Send(new GpuMsg_CreateViewCommandBuffer(
639c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          compositing_surface, surface_id, client_id, init_params, route_id))) {
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    create_command_buffer_requests_.push(callback);
641c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    surface_refs_.insert(std::make_pair(surface_id,
642c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        GpuSurfaceTracker::GetInstance()->GetSurfaceRefForSurface(surface_id)));
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
644116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // Could distinguish here between compositing_surface being NULL
645116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // and Send failing, if desired.
646116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    callback.Run(CREATE_COMMAND_BUFFER_FAILED_AND_CHANNEL_LOST);
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
650f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void GpuProcessHost::CreateGpuMemoryBuffer(
651f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const gfx::GpuMemoryBufferHandle& handle,
652f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const gfx::Size& size,
653f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    unsigned internalformat,
654f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    unsigned usage,
655f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const CreateGpuMemoryBufferCallback& callback) {
656f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuProcessHost::CreateGpuMemoryBuffer");
657f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
658f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(CalledOnValidThread());
659f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
660f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (Send(new GpuMsg_CreateGpuMemoryBuffer(
661f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          handle, size, internalformat, usage))) {
662f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    create_gpu_memory_buffer_requests_.push(callback);
663f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else {
664f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    callback.Run(gfx::GpuMemoryBufferHandle());
665f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
666f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
667f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
668f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void GpuProcessHost::DestroyGpuMemoryBuffer(
669f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const gfx::GpuMemoryBufferHandle& handle,
670f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    int sync_point) {
671f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuProcessHost::DestroyGpuMemoryBuffer");
672f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
673f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(CalledOnValidThread());
674f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
675f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Send(new GpuMsg_DestroyGpuMemoryBuffer(handle, sync_point));
676f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
677f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
67890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void GpuProcessHost::OnInitialized(bool result, const gpu::GPUInfo& gpu_info) {
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_BOOLEAN("GPU.GPUProcessInitialized", result);
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  initialized_ = result;
68190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
682eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!initialized_)
683eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    GpuDataManagerImpl::GetInstance()->OnGpuProcessInitFailure();
684effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  else if (!in_process_)
685effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    GpuDataManagerImpl::GetInstance()->UpdateGpuInfo(gpu_info);
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuProcessHost::OnChannelEstablished(
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPC::ChannelHandle& channel_handle) {
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT0("gpu", "GpuProcessHost::OnChannelEstablished");
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
692c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (channel_requests_.empty()) {
693c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // This happens when GPU process is compromised.
694c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RouteOnUIThread(GpuHostMsg_OnLogMessage(
695c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        logging::LOG_WARNING,
696c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        "WARNING",
697c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        "Received a ChannelEstablished message but no requests in queue."));
698c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
699c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EstablishChannelCallback callback = channel_requests_.front();
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel_requests_.pop();
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Currently if any of the GPU features are blacklisted, we don't establish a
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GPU channel.
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!channel_handle.name.empty() &&
706c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      !GpuDataManagerImpl::GetInstance()->GpuAccessAllowed(NULL)) {
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(new GpuMsg_CloseChannel(channel_handle));
70890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    callback.Run(IPC::ChannelHandle(), gpu::GPUInfo());
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RouteOnUIThread(GpuHostMsg_OnLogMessage(
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        logging::LOG_WARNING,
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "WARNING",
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "Hardware acceleration is unavailable."));
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.Run(channel_handle,
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               GpuDataManagerImpl::GetInstance()->GetGPUInfo());
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
720116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid GpuProcessHost::OnCommandBufferCreated(CreateCommandBufferResult result) {
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT0("gpu", "GpuProcessHost::OnCommandBufferCreated");
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (create_command_buffer_requests_.empty())
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateCommandBufferCallback callback =
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      create_command_buffer_requests_.front();
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  create_command_buffer_requests_.pop();
729116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  callback.Run(result);
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuProcessHost::OnDestroyCommandBuffer(int32 surface_id) {
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT0("gpu", "GpuProcessHost::OnDestroyCommandBuffer");
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SurfaceRefMap::iterator it = surface_refs_.find(surface_id);
735c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (it != surface_refs_.end()) {
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    surface_refs_.erase(it);
737c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
740f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void GpuProcessHost::OnGpuMemoryBufferCreated(
741f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const gfx::GpuMemoryBufferHandle& handle) {
742f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuProcessHost::OnGpuMemoryBufferCreated");
743f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
744f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (create_gpu_memory_buffer_requests_.empty())
745f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
746f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
747f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CreateGpuMemoryBufferCallback callback =
748f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      create_gpu_memory_buffer_requests_.front();
749f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  create_gpu_memory_buffer_requests_.pop();
750f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  callback.Run(handle);
751f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
752f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuProcessHost::OnDidCreateOffscreenContext(const GURL& url) {
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  urls_with_live_offscreen_contexts_.insert(url);
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuProcessHost::OnDidLoseContext(bool offscreen,
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      gpu::error::ContextLostReason reason,
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      const GURL& url) {
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(kbr): would be nice to see the "offscreen" flag too.
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT2("gpu", "GpuProcessHost::OnDidLoseContext",
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               "reason", reason,
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               "url",
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               url.possibly_invalid_spec());
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!offscreen || url.is_empty()) {
7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Assume that the loss of the compositor's or accelerated canvas'
7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // context is a serious event and blame the loss on all live
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // offscreen contexts. This more robustly handles situations where
7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // the GPU process may not actually detect the context loss in the
7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // offscreen context.
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BlockLiveOffscreenContexts();
7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GpuDataManagerImpl::DomainGuilt guilt;
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (reason) {
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case gpu::error::kGuilty:
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      guilt = GpuDataManagerImpl::DOMAIN_GUILT_KNOWN;
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case gpu::error::kUnknown:
7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      guilt = GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN;
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case gpu::error::kInnocent:
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NOTREACHED();
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs(url, guilt);
7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuProcessHost::OnDidDestroyOffscreenContext(const GURL& url) {
7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  urls_with_live_offscreen_contexts_.erase(url);
7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuProcessHost::OnGpuMemoryUmaStatsReceived(
7992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GPUMemoryUmaStats& stats) {
8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT0("gpu", "GpuProcessHost::OnGpuMemoryUmaStatsReceived");
8012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uma_memory_stats_received_ = true;
8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uma_memory_stats_ = stats;
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
806116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid GpuProcessHost::OnAcceleratedSurfaceBuffersSwapped(
807116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const IPC::Message& message) {
808116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  RenderWidgetResizeHelper::Get()->PostGpuProcessMsg(host_id_, message);
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
810116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuProcessHost::OnProcessLaunched() {
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_TIMES("GPU.GPUProcessLaunchTime",
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      base::TimeTicks::Now() - init_start_time_);
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuProcessHost::OnProcessCrashed(int exit_code) {
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendOutstandingReplies();
8195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  RecordProcessCrash();
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GpuDataManagerImpl::GetInstance()->ProcessCrashed(
821424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      process_->GetTerminationStatus(true /* known_dead */, NULL));
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuProcessHost::GpuProcessKind GpuProcessHost::kind() {
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return kind_;
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuProcessHost::ForceShutdown() {
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is only called on the IO thread so no race against the constructor
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for another GpuProcessHost.
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g_gpu_process_hosts[kind_] == this)
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_gpu_process_hosts[kind_] = NULL;
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process_->ForceShutdown();
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuProcessHost::BeginFrameSubscription(
8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int surface_id,
8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::WeakPtr<RenderWidgetHostViewFrameSubscriber> subscriber) {
8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame_subscribers_[surface_id] = subscriber;
8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuProcessHost::EndFrameSubscription(int surface_id) {
8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame_subscribers_.erase(surface_id);
8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuProcessHost::LaunchGpuProcess(const std::string& channel_id) {
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!(gpu_enabled_ &&
849c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GpuDataManagerImpl::GetInstance()->ShouldUseSwiftShader()) &&
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !hardware_gpu_enabled_) {
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendOutstandingReplies();
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  const base::CommandLine& browser_command_line =
8566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      *base::CommandLine::ForCurrentProcess();
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::CommandLine::StringType gpu_launcher =
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser_command_line.GetSwitchValueNative(switches::kGpuLauncher);
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX)
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int child_flags = gpu_launcher.empty() ? ChildProcessHost::CHILD_ALLOW_SELF :
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           ChildProcessHost::CHILD_NORMAL;
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int child_flags = ChildProcessHost::CHILD_NORMAL;
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath exe_path = ChildProcessHost::GetChildPath(child_flags);
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (exe_path.empty())
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::CommandLine* cmd_line = new base::CommandLine(exe_path);
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kGpuProcess);
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id);
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (kind_ == GPU_PROCESS_KIND_UNSANDBOXED)
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cmd_line->AppendSwitch(switches::kDisableGpuSandbox);
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // If you want a browser command-line switch passed to the GPU process
8801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // you need to add it to |kSwitchNames| at the beginning of this file.
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cmd_line->CopySwitchesFrom(browser_command_line, kSwitchNames,
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             arraysize(kSwitchNames));
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cmd_line->CopySwitchesFrom(
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser_command_line, switches::kGpuSwitches, switches::kNumGpuSwitches);
8852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  cmd_line->CopySwitchesFrom(
8862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      browser_command_line, switches::kGLSwitchesCopiedFromGpuProcessHost,
8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      switches::kGLSwitchesCopiedFromGpuProcessHostNumSwitches);
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetContentClient()->browser()->AppendExtraCommandLineSwitches(
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cmd_line, process_->GetData().id);
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GpuDataManagerImpl::GetInstance()->AppendGpuCommandLine(cmd_line);
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (cmd_line->HasSwitch(switches::kUseGL)) {
895c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    swiftshader_rendering_ =
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (cmd_line->GetSwitchValueASCII(switches::kUseGL) == "swiftshader");
8972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
899c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UMA_HISTOGRAM_BOOLEAN("GPU.GPU.GPUProcessSoftwareRendering",
900c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        swiftshader_rendering_);
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If specified, prepend a launcher program to the command line.
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!gpu_launcher.empty())
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cmd_line->PrependWrapper(gpu_launcher);
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process_->Launch(
907a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      new GpuSandboxedProcessLauncherDelegate(cmd_line,
908a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                              process_->GetHost()),
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cmd_line);
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process_launched_ = true;
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents",
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            LAUNCHED, GPU_PROCESS_LIFETIME_EVENT_MAX);
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuProcessHost::SendOutstandingReplies() {
9182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  valid_ = false;
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First send empty channel handles for all EstablishChannel requests.
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!channel_requests_.empty()) {
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EstablishChannelCallback callback = channel_requests_.front();
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel_requests_.pop();
92390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    callback.Run(IPC::ChannelHandle(), gpu::GPUInfo());
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
925c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
926c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while (!create_command_buffer_requests_.empty()) {
927c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CreateCommandBufferCallback callback =
928c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        create_command_buffer_requests_.front();
929c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    create_command_buffer_requests_.pop();
930116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    callback.Run(CREATE_COMMAND_BUFFER_FAILED_AND_CHANNEL_LOST);
931c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
9321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
9331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  while (!create_gpu_memory_buffer_requests_.empty()) {
9341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    CreateGpuMemoryBufferCallback callback =
9351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        create_gpu_memory_buffer_requests_.front();
9361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    create_gpu_memory_buffer_requests_.pop();
9371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback.Run(gfx::GpuMemoryBufferHandle());
9381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuProcessHost::BlockLiveOffscreenContexts() {
9422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::multiset<GURL>::iterator iter =
9432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           urls_with_live_offscreen_contexts_.begin();
9442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != urls_with_live_offscreen_contexts_.end(); ++iter) {
9452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs(
9462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        *iter, GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN);
9472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void GpuProcessHost::RecordProcessCrash() {
9515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Skip if a GPU process crash was already counted.
9525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (gpu_crash_recorded_)
9535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
9545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Maximum number of times the GPU process is allowed to crash in a session.
9561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Once this limit is reached, any request to launch the GPU process will
9575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // fail.
9585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const int kGpuMaxCrashCount = 3;
9595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Last time the GPU process crashed.
9615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  static base::Time last_gpu_crash_time;
9625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  bool disable_crash_limit = base::CommandLine::ForCurrentProcess()->HasSwitch(
9645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      switches::kDisableGpuProcessCrashLimit);
9655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Ending only acts as a failure if the GPU process was actually started and
9675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // was intended for actual rendering (and not just checking caps or other
9685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // options).
9695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (process_launched_ && kind_ == GPU_PROCESS_KIND_SANDBOXED) {
9705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    gpu_crash_recorded_ = true;
9715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (swiftshader_rendering_) {
9725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      UMA_HISTOGRAM_ENUMERATION("GPU.SwiftShaderLifetimeEvents",
9735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                DIED_FIRST_TIME + swiftshader_crash_count_,
9745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                GPU_PROCESS_LIFETIME_EVENT_MAX);
9755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (++swiftshader_crash_count_ >= kGpuMaxCrashCount &&
9775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          !disable_crash_limit) {
9785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        // SwiftShader is too unstable to use. Disable it for current session.
9795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        gpu_enabled_ = false;
9805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
9815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    } else {
9825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ++gpu_crash_count_;
9835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents",
9845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                std::min(DIED_FIRST_TIME + gpu_crash_count_,
9855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                         GPU_PROCESS_LIFETIME_EVENT_MAX - 1),
9865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                GPU_PROCESS_LIFETIME_EVENT_MAX);
9875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // Allow about 1 GPU crash per hour to be removed from the crash count,
9895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // so very occasional crashes won't eventually add up and prevent the
9905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // GPU process from launching.
9915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ++gpu_recent_crash_count_;
9925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::Time current_time = base::Time::Now();
9935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (crashed_before_) {
9945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        int hours_different = (current_time - last_gpu_crash_time).InHours();
9955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        gpu_recent_crash_count_ =
9965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            std::max(0, gpu_recent_crash_count_ - hours_different);
9975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
9985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      crashed_before_ = true;
10005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      last_gpu_crash_time = current_time;
10015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if ((gpu_recent_crash_count_ >= kGpuMaxCrashCount &&
10035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)           !disable_crash_limit) ||
10045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          !initialized_) {
10055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if !defined(OS_CHROMEOS)
10061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        // The GPU process is too unstable to use. Disable it for current
10075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        // session.
10085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        hardware_gpu_enabled_ = false;
10095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        GpuDataManagerImpl::GetInstance()->DisableHardwareAcceleration();
10105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
10115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
10125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
10135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
10145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
10155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string GpuProcessHost::GetShaderPrefixKey() {
10172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (shader_prefix_key_.empty()) {
101890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    gpu::GPUInfo info = GpuDataManagerImpl::GetInstance()->GetGPUInfo();
10192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string in_str = GetContentClient()->GetProduct() + "-" +
10212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        info.gl_vendor + "-" + info.gl_renderer + "-" +
10222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        info.driver_version + "-" + info.driver_vendor;
10232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::Base64Encode(base::SHA1HashString(in_str), &shader_prefix_key_);
10252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
10262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return shader_prefix_key_;
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuProcessHost::LoadedShader(const std::string& key,
10312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  const std::string& data) {
10322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string prefix = GetShaderPrefixKey();
10332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!key.compare(0, prefix.length(), prefix))
10342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Send(new GpuMsg_LoadedShader(data));
10352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void GpuProcessHost::CreateChannelCache(int32 client_id) {
10382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT0("gpu", "GpuProcessHost::CreateChannelCache");
10392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<ShaderDiskCache> cache =
10412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ShaderCacheFactory::GetInstance()->Get(client_id);
1042868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!cache.get())
10432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
10442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  cache->set_host_id(host_id_);
10462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_id_to_shader_cache_[client_id] = cache;
10482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuProcessHost::OnDestroyChannel(int32 client_id) {
10512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT0("gpu", "GpuProcessHost::OnDestroyChannel");
10522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_id_to_shader_cache_.erase(client_id);
10532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuProcessHost::OnCacheShader(int32 client_id,
10562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   const std::string& key,
10572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   const std::string& shader) {
10582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT0("gpu", "GpuProcessHost::OnCacheShader");
10592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClientIdToShaderCacheMap::iterator iter =
10602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      client_id_to_shader_cache_.find(client_id);
10612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If the cache doesn't exist then this is an off the record profile.
10622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (iter == client_id_to_shader_cache_.end())
10632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
10642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  iter->second->Cache(GetShaderPrefixKey() + ":" + key, shader);
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
1068