gpu_process_host.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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"
4368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/events/latency_info.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_switches.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(OS_MACOSX)
47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include <IOSurface/IOSurfaceAPI.h>
48116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/mac/scoped_cftyperef.h"
49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/common/gpu/surface_handle_types_mac.h"
50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/win/windows_version.h"
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/common/sandbox_win.h"
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sandbox/win/src/sandbox_policy.h"
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/switches.h"
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(USE_OZONE)
60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "ui/ozone/public/ozone_switches.h"
61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif
62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(USE_X11) && !defined(OS_CHROMEOS)
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/gfx/x/x11_switches.h"
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuProcessHost::gpu_enabled_ = true;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuProcessHost::hardware_gpu_enabled_ = true;
715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int GpuProcessHost::gpu_crash_count_ = 0;
725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int GpuProcessHost::gpu_recent_crash_count_ = 0;
735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool GpuProcessHost::crashed_before_ = false;
745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int GpuProcessHost::swiftshader_crash_count_ = 0;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum GPUProcessLifetimeEvent {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LAUNCHED,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DIED_FIRST_TIME,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DIED_SECOND_TIME,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DIED_THIRD_TIME,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DIED_FOURTH_TIME,
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GPU_PROCESS_LIFETIME_EVENT_MAX = 100
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Indexed by GpuProcessKind. There is one of each kind maximum. This array may
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// only be accessed from the IO thread.
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)GpuProcessHost* g_gpu_process_hosts[GpuProcessHost::GPU_PROCESS_KIND_COUNT];
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SendGpuProcessMessage(GpuProcessHost::GpuProcessKind kind,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           CauseForGpuLaunch cause,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           IPC::Message* message) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GpuProcessHost* host = GpuProcessHost::Get(kind, cause);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host->Send(message);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete message;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// NOTE: changes to this class need to be reviewed by the security team.
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class GpuSandboxedProcessLauncherDelegate
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public SandboxedProcessLauncherDelegate {
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GpuSandboxedProcessLauncherDelegate(CommandLine* cmd_line,
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                      ChildProcessHost* host)
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(OS_WIN)
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : cmd_line_(cmd_line) {}
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#elif defined(OS_POSIX)
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      : ipc_fd_(host->TakeClientFileDescriptor()) {}
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~GpuSandboxedProcessLauncherDelegate() {}
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(OS_WIN)
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual bool ShouldSandbox() OVERRIDE {
119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    bool sandbox = !cmd_line_->HasSwitch(switches::kDisableGpuSandbox);
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if(! sandbox) {
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DVLOG(1) << "GPU sandbox is disabled";
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return sandbox;
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void PreSandbox(bool* disable_default_policy,
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          base::FilePath* exposed_dir) OVERRIDE {
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *disable_default_policy = true;
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // For the GPU process we gotten as far as USER_LIMITED. The next level
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // which is USER_RESTRICTED breaks both the DirectX backend and the OpenGL
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // backend. Note that the GPU process is connected to the interactive
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // desktop.
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void PreSpawnTarget(sandbox::TargetPolicy* policy,
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              bool* success) {
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (base::win::GetVersion() > base::win::VERSION_XP) {
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (cmd_line_->GetSwitchValueASCII(switches::kUseGL) ==
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          gfx::kGLImplementationDesktopName) {
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // Open GL path.
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              sandbox::USER_LIMITED);
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SetJobLevel(*cmd_line_, sandbox::JOB_UNPROTECTED, 0, policy);
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                              sandbox::USER_LIMITED);
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // UI restrictions break when we access Windows from outside our job.
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // However, we don't want a proxy window in this process because it can
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // introduce deadlocks where the renderer blocks on the gpu, which in
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // turn blocks on the browser UI thread. So, instead we forgo a window
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // message pump entirely and just add job restrictions to prevent child
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // processes.
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SetJobLevel(*cmd_line_,
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    sandbox::JOB_LIMITED_USER,
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS |
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    JOB_OBJECT_UILIMIT_DESKTOP |
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    JOB_OBJECT_UILIMIT_EXITWINDOWS |
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    JOB_OBJECT_UILIMIT_DISPLAYSETTINGS,
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    policy);
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        policy->SetIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SetJobLevel(*cmd_line_, sandbox::JOB_UNPROTECTED, 0, policy);
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      policy->SetTokenLevel(sandbox::USER_UNPROTECTED,
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            sandbox::USER_LIMITED);
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Allow the server side of GPU sockets, which are pipes that have
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // the "chrome.gpu" namespace and an arbitrary suffix.
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sandbox::ResultCode result = policy->AddRule(
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        sandbox::TargetPolicy::SUBSYS_NAMED_PIPES,
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        sandbox::TargetPolicy::NAMEDPIPES_ALLOW_ANY,
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        L"\\\\.\\pipe\\chrome.gpu.*");
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (result != sandbox::SBOX_ALL_OK) {
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *success = false;
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Block this DLL even if it is not loaded by the browser process.
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    policy->AddDllToUnload(L"cmsetac.dll");
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifdef USE_AURA
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // GPU also needs to add sections to the browser for aura
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TODO(jschuh): refactor the GPU channel to remove this. crbug.com/128786
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES,
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             sandbox::TargetPolicy::HANDLES_DUP_BROKER,
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             L"Section");
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (result != sandbox::SBOX_ALL_OK) {
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *success = false;
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (cmd_line_->HasSwitch(switches::kEnableLogging)) {
198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::string16 log_file_path = logging::GetLogFileFullPath();
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!log_file_path.empty()) {
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 sandbox::TargetPolicy::FILES_ALLOW_ANY,
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 log_file_path.c_str());
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (result != sandbox::SBOX_ALL_OK) {
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          *success = false;
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          return;
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#elif defined(OS_POSIX)
211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual int GetIpcFd() OVERRIDE {
213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return ipc_fd_;
214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif  // OS_WIN
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(OS_WIN)
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CommandLine* cmd_line_;
220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#elif defined(OS_POSIX)
221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int ipc_fd_;
222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif  // OS_WIN
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // anonymous namespace
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GpuProcessHost::ValidateHost(GpuProcessHost* host) {
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The Gpu process is invalid if it's not using SwiftShader, the card is
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // blacklisted, and we can kill it and start over.
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) ||
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU) ||
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (host->valid_ &&
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       (host->swiftshader_rendering_ ||
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        !GpuDataManagerImpl::GetInstance()->ShouldUseSwiftShader()))) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  host->ForceShutdown();
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuProcessHost* GpuProcessHost::Get(GpuProcessKind kind,
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    CauseForGpuLaunch cause) {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't grant further access to GPU if it is not allowed.
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance();
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(gpu_data_manager);
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!gpu_data_manager->GpuAccessAllowed(NULL))
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (g_gpu_process_hosts[kind] && ValidateHost(g_gpu_process_hosts[kind]))
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return g_gpu_process_hosts[kind];
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cause == CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static int last_host_id = 0;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int host_id;
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  host_id = ++last_host_id;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLaunchCause",
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            cause,
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            CAUSE_FOR_GPU_LAUNCH_MAX_ENUM);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GpuProcessHost* host = new GpuProcessHost(host_id, kind);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host->Init())
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return host;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete host;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuProcessHost::GetProcessHandles(
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GpuDataManager::GetGpuProcessHandlesCallback& callback)  {
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BrowserThread::PostTask(
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        BrowserThread::IO,
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&GpuProcessHost::GetProcessHandles, callback));
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::list<base::ProcessHandle> handles;
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < arraysize(g_gpu_process_hosts); ++i) {
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GpuProcessHost* host = g_gpu_process_hosts[i];
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (host && ValidateHost(host))
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      handles.push_back(host->process_->GetHandle());
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BrowserThread::PostTask(
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      BrowserThread::UI,
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(callback, handles));
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuProcessHost::SendOnIO(GpuProcessKind kind,
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              CauseForGpuLaunch cause,
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              IPC::Message* message) {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!BrowserThread::PostTask(
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          BrowserThread::IO, FROM_HERE,
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              &SendGpuProcessMessage, kind, cause, message))) {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete message;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)GpuMainThreadFactoryFunction g_gpu_main_thread_factory = NULL;
3113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void GpuProcessHost::RegisterGpuMainThreadFactory(
3133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    GpuMainThreadFactoryFunction create) {
3143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  g_gpu_main_thread_factory = create;
3153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuProcessHost* GpuProcessHost::FromID(int host_id) {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < GPU_PROCESS_KIND_COUNT; ++i) {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GpuProcessHost* host = g_gpu_process_hosts[i];
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (host && host->host_id_ == host_id && ValidateHost(host))
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return host;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuProcessHost::GpuProcessHost(int host_id, GpuProcessKind kind)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : host_id_(host_id),
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      valid_(true),
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      in_process_(false),
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      swiftshader_rendering_(false),
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kind_(kind),
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      process_launched_(false),
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      initialized_(false),
3385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      gpu_crash_recorded_(false),
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      uma_memory_stats_received_(false) {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) ||
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU)) {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    in_process_ = true;
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the 'single GPU process' policy ever changes, we still want to maintain
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it for 'gpu thread' mode and only create one instance of host and thread.
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!in_process_ || g_gpu_process_hosts[kind] == NULL);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_gpu_process_hosts[kind] = this;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Post a task to create the corresponding GpuProcessHostUIShim.  The
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GpuProcessHostUIShim will be destroyed if either the browser exits,
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in which case it calls GpuProcessHostUIShim::DestroyAll, or the
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GpuProcessHost is destroyed, which happens when the corresponding GPU
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // process terminates or fails to launch.
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::UI,
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(base::IgnoreResult(&GpuProcessHostUIShim::Create), host_id));
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process_.reset(new BrowserChildProcessHostImpl(PROCESS_TYPE_GPU, this));
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuProcessHost::~GpuProcessHost() {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendOutstandingReplies();
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  RecordProcessCrash();
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // In case we never started, clean up.
372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  while (!queued_messages_.empty()) {
373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    delete queued_messages_.front();
374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    queued_messages_.pop();
375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // This is only called on the IO thread so no race against the constructor
378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // for another GpuProcessHost.
379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (g_gpu_process_hosts[kind_] == this)
380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    g_gpu_process_hosts[kind_] = NULL;
381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
382868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // If there are any remaining offscreen contexts at the point the
383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // GPU process exits, assume something went wrong, and block their
384868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // URLs from accessing client 3D APIs without prompting.
385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  BlockLiveOffscreenContexts();
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UMA_HISTOGRAM_COUNTS_100("GPU.AtExitSurfaceCount",
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           GpuSurfaceTracker::Get()->GetSurfaceCount());
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UMA_HISTOGRAM_BOOLEAN("GPU.AtExitReceivedMemoryStats",
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        uma_memory_stats_received_);
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (uma_memory_stats_received_) {
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UMA_HISTOGRAM_COUNTS_100("GPU.AtExitManagedMemoryClientCount",
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             uma_memory_stats_.client_count);
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UMA_HISTOGRAM_COUNTS_100("GPU.AtExitContextGroupCount",
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             uma_memory_stats_.context_group_count);
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UMA_HISTOGRAM_CUSTOM_COUNTS(
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "GPU.AtExitMBytesAllocated",
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        uma_memory_stats_.bytes_allocated_current / 1024 / 1024, 1, 2000, 50);
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UMA_HISTOGRAM_CUSTOM_COUNTS(
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "GPU.AtExitMBytesAllocatedMax",
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        uma_memory_stats_.bytes_allocated_max / 1024 / 1024, 1, 2000, 50);
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UMA_HISTOGRAM_CUSTOM_COUNTS(
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "GPU.AtExitMBytesLimit",
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        uma_memory_stats_.bytes_limit / 1024 / 1024, 1, 2000, 50);
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string message;
409868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!in_process_) {
410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int exit_code;
411424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    base::TerminationStatus status = process_->GetTerminationStatus(
412424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        false /* known_dead */, &exit_code);
413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessTerminationStatus",
414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              status,
415868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              base::TERMINATION_STATUS_MAX_ENUM);
416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
417868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (status == base::TERMINATION_STATUS_NORMAL_TERMINATION ||
418868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION) {
419868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessExitCode",
420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                exit_code,
421868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                RESULT_CODE_LAST_CODE);
422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
423868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
424868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    switch (status) {
425868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      case base::TERMINATION_STATUS_NORMAL_TERMINATION:
426868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        message = "The GPU process exited normally. Everything is okay.";
427868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        break;
428868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
429868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        message = base::StringPrintf(
430868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            "The GPU process exited with code %d.",
431868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            exit_code);
432868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        break;
433868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
434868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        message = "You killed the GPU process! Why?";
435868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        break;
436868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      case base::TERMINATION_STATUS_PROCESS_CRASHED:
437868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        message = "The GPU process crashed!";
438868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        break;
439868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      default:
440868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        break;
441868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::UI,
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          FROM_HERE,
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          base::Bind(&GpuProcessHostUIShim::Destroy,
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     host_id_,
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     message));
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuProcessHost::Init() {
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_start_time_ = base::TimeTicks::Now();
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TRACE_EVENT_INSTANT0("gpu", "LaunchGpuProcess", TRACE_EVENT_SCOPE_THREAD);
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string channel_id = process_->GetHost()->CreateChannel();
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (channel_id.empty())
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
460f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (in_process_) {
461f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(g_gpu_main_thread_factory);
4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CommandLine* command_line = CommandLine::ForCurrentProcess();
4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    command_line->AppendSwitch(switches::kDisableGpuWatchdog);
4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance();
4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(gpu_data_manager);
4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gpu_data_manager->AppendGpuCommandLine(command_line);
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    in_process_gpu_thread_.reset(g_gpu_main_thread_factory(channel_id));
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    in_process_gpu_thread_->Start();
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnProcessLaunched();  // Fake a callback that the process is ready.
4733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else if (!LaunchGpuProcess(channel_id)) {
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Send(new GpuMsg_Initialize()))
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuProcessHost::RouteOnUIThread(const IPC::Message& message) {
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::UI,
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&RouteToGpuProcessHostUIShimTask, host_id_, message));
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuProcessHost::Send(IPC::Message* msg) {
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (process_->GetHost()->IsChannelOpening()) {
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    queued_messages_.push(msg);
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool result = process_->Send(msg);
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!result) {
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Channel is hosed, but we may not get destroyed for a while. Send
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // outstanding channel creation failures now so that the caller can restart
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // with a new process/channel without waiting.
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SendOutstandingReplies();
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid GpuProcessHost::AddFilter(IPC::MessageFilter* filter) {
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process_->GetHost()->AddFilter(filter);
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuProcessHost::OnMessageReceived(const IPC::Message& message) {
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(GpuProcessHost, message)
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuHostMsg_Initialized, OnInitialized)
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuHostMsg_ChannelEstablished, OnChannelEstablished)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuHostMsg_CommandBufferCreated, OnCommandBufferCreated)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuHostMsg_DestroyCommandBuffer, OnDestroyCommandBuffer)
519f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuHostMsg_GpuMemoryBufferCreated,
520f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        OnGpuMemoryBufferCreated)
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuHostMsg_DidCreateOffscreenContext,
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        OnDidCreateOffscreenContext)
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuHostMsg_DidLoseContext, OnDidLoseContext)
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuHostMsg_DidDestroyOffscreenContext,
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        OnDidDestroyOffscreenContext)
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuHostMsg_GpuMemoryUmaStats,
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        OnGpuMemoryUmaStatsReceived)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
529116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    IPC_MESSAGE_HANDLER_GENERIC(GpuHostMsg_AcceleratedSurfaceBuffersSwapped,
530116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                OnAcceleratedSurfaceBuffersSwapped(message))
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuHostMsg_DestroyChannel,
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        OnDestroyChannel)
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuHostMsg_CacheShader,
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        OnCacheShader)
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_UNHANDLED(RouteOnUIThread(message))
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_END_MESSAGE_MAP()
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuProcessHost::OnChannelConnected(int32 peer_pid) {
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT0("gpu", "GpuProcessHost::OnChannelConnected");
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!queued_messages_.empty()) {
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(queued_messages_.front());
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    queued_messages_.pop();
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuProcessHost::EstablishGpuChannel(
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int client_id,
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool share_context,
555116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    bool allow_future_sync_points,
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EstablishChannelCallback& callback) {
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT0("gpu", "GpuProcessHost::EstablishGpuChannel");
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If GPU features are already blacklisted, no need to establish the channel.
561c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!GpuDataManagerImpl::GetInstance()->GpuAccessAllowed(NULL)) {
562a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DVLOG(1) << "GPU blacklisted, refusing to open a GPU channel.";
56390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    callback.Run(IPC::ChannelHandle(), gpu::GPUInfo());
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
567116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (Send(new GpuMsg_EstablishChannel(
568116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          client_id, share_context, allow_future_sync_points))) {
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel_requests_.push(callback);
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
571a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DVLOG(1) << "Failed to send GpuMsg_EstablishChannel.";
57290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    callback.Run(IPC::ChannelHandle(), gpu::GPUInfo());
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!CommandLine::ForCurrentProcess()->HasSwitch(
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      switches::kDisableGpuShaderDiskCache)) {
5777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    CreateChannelCache(client_id);
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuProcessHost::CreateViewCommandBuffer(
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::GLSurfaceHandle& compositing_surface,
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int surface_id,
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int client_id,
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GPUCreateCommandBufferConfig& init_params,
586c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    int route_id,
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const CreateCommandBufferCallback& callback) {
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT0("gpu", "GpuProcessHost::CreateViewCommandBuffer");
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!compositing_surface.is_null() &&
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Send(new GpuMsg_CreateViewCommandBuffer(
594c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          compositing_surface, surface_id, client_id, init_params, route_id))) {
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    create_command_buffer_requests_.push(callback);
596c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    surface_refs_.insert(std::make_pair(surface_id,
597c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        GpuSurfaceTracker::GetInstance()->GetSurfaceRefForSurface(surface_id)));
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
599116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // Could distinguish here between compositing_surface being NULL
600116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // and Send failing, if desired.
601116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    callback.Run(CREATE_COMMAND_BUFFER_FAILED_AND_CHANNEL_LOST);
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void GpuProcessHost::CreateGpuMemoryBuffer(
606f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const gfx::GpuMemoryBufferHandle& handle,
607f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const gfx::Size& size,
608f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    unsigned internalformat,
609f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    unsigned usage,
610f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const CreateGpuMemoryBufferCallback& callback) {
611f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuProcessHost::CreateGpuMemoryBuffer");
612f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
613f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(CalledOnValidThread());
614f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
615f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (Send(new GpuMsg_CreateGpuMemoryBuffer(
616f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          handle, size, internalformat, usage))) {
617f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    create_gpu_memory_buffer_requests_.push(callback);
618f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else {
619f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    callback.Run(gfx::GpuMemoryBufferHandle());
620f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
621f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
622f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
623f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void GpuProcessHost::DestroyGpuMemoryBuffer(
624f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const gfx::GpuMemoryBufferHandle& handle,
625f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    int sync_point) {
626f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuProcessHost::DestroyGpuMemoryBuffer");
627f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
628f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(CalledOnValidThread());
629f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
630f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Send(new GpuMsg_DestroyGpuMemoryBuffer(handle, sync_point));
631f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
632f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
63390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void GpuProcessHost::OnInitialized(bool result, const gpu::GPUInfo& gpu_info) {
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_BOOLEAN("GPU.GPUProcessInitialized", result);
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  initialized_ = result;
63690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
637eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!initialized_)
638eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    GpuDataManagerImpl::GetInstance()->OnGpuProcessInitFailure();
639effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  else if (!in_process_)
640effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    GpuDataManagerImpl::GetInstance()->UpdateGpuInfo(gpu_info);
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuProcessHost::OnChannelEstablished(
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPC::ChannelHandle& channel_handle) {
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT0("gpu", "GpuProcessHost::OnChannelEstablished");
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
647c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (channel_requests_.empty()) {
648c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // This happens when GPU process is compromised.
649c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RouteOnUIThread(GpuHostMsg_OnLogMessage(
650c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        logging::LOG_WARNING,
651c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        "WARNING",
652c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        "Received a ChannelEstablished message but no requests in queue."));
653c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
654c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EstablishChannelCallback callback = channel_requests_.front();
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel_requests_.pop();
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Currently if any of the GPU features are blacklisted, we don't establish a
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GPU channel.
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!channel_handle.name.empty() &&
661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      !GpuDataManagerImpl::GetInstance()->GpuAccessAllowed(NULL)) {
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(new GpuMsg_CloseChannel(channel_handle));
66390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    callback.Run(IPC::ChannelHandle(), gpu::GPUInfo());
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RouteOnUIThread(GpuHostMsg_OnLogMessage(
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        logging::LOG_WARNING,
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "WARNING",
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "Hardware acceleration is unavailable."));
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.Run(channel_handle,
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               GpuDataManagerImpl::GetInstance()->GetGPUInfo());
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid GpuProcessHost::OnCommandBufferCreated(CreateCommandBufferResult result) {
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT0("gpu", "GpuProcessHost::OnCommandBufferCreated");
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (create_command_buffer_requests_.empty())
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateCommandBufferCallback callback =
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      create_command_buffer_requests_.front();
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  create_command_buffer_requests_.pop();
684116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  callback.Run(result);
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuProcessHost::OnDestroyCommandBuffer(int32 surface_id) {
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT0("gpu", "GpuProcessHost::OnDestroyCommandBuffer");
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SurfaceRefMap::iterator it = surface_refs_.find(surface_id);
690c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (it != surface_refs_.end()) {
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    surface_refs_.erase(it);
692c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void GpuProcessHost::OnGpuMemoryBufferCreated(
696f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const gfx::GpuMemoryBufferHandle& handle) {
697f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuProcessHost::OnGpuMemoryBufferCreated");
698f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
699f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (create_gpu_memory_buffer_requests_.empty())
700f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
701f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
702f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CreateGpuMemoryBufferCallback callback =
703f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      create_gpu_memory_buffer_requests_.front();
704f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  create_gpu_memory_buffer_requests_.pop();
705f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  callback.Run(handle);
706f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
707f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuProcessHost::OnDidCreateOffscreenContext(const GURL& url) {
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  urls_with_live_offscreen_contexts_.insert(url);
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuProcessHost::OnDidLoseContext(bool offscreen,
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      gpu::error::ContextLostReason reason,
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      const GURL& url) {
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(kbr): would be nice to see the "offscreen" flag too.
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT2("gpu", "GpuProcessHost::OnDidLoseContext",
7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               "reason", reason,
7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               "url",
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               url.possibly_invalid_spec());
7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!offscreen || url.is_empty()) {
7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Assume that the loss of the compositor's or accelerated canvas'
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // context is a serious event and blame the loss on all live
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // offscreen contexts. This more robustly handles situations where
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // the GPU process may not actually detect the context loss in the
7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // offscreen context.
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BlockLiveOffscreenContexts();
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GpuDataManagerImpl::DomainGuilt guilt;
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (reason) {
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case gpu::error::kGuilty:
7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      guilt = GpuDataManagerImpl::DOMAIN_GUILT_KNOWN;
7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case gpu::error::kUnknown:
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      guilt = GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN;
7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case gpu::error::kInnocent:
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NOTREACHED();
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs(url, guilt);
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuProcessHost::OnDidDestroyOffscreenContext(const GURL& url) {
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  urls_with_live_offscreen_contexts_.erase(url);
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuProcessHost::OnGpuMemoryUmaStatsReceived(
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GPUMemoryUmaStats& stats) {
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT0("gpu", "GpuProcessHost::OnGpuMemoryUmaStatsReceived");
7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uma_memory_stats_received_ = true;
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uma_memory_stats_ = stats;
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
761116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace {
762116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid HoldIOSurfaceReference(base::ScopedCFTypeRef<IOSurfaceRef> io_surface) {}
763116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}  // namespace
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid GpuProcessHost::OnAcceleratedSurfaceBuffersSwapped(
766116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const IPC::Message& message) {
767116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  RenderWidgetResizeHelper::Get()->PostGpuProcessMsg(host_id_, message);
7685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
769116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!IsDelegatedRendererEnabled())
770cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
771cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
772116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  GpuHostMsg_AcceleratedSurfaceBuffersSwapped::Param param;
773116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!GpuHostMsg_AcceleratedSurfaceBuffersSwapped::Read(&message, &param))
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
775116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params = param.a;
776116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
777116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (GetSurfaceHandleType(params.surface_handle) ==
778116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          kSurfaceHandleTypeIOSurface) {
779116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // As soon as the frame is acked, the IOSurface may be thrown away by the
780116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // GPU process. Open the IOSurface and post a task referencing it to the UI
781116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // thread. This will keep the IOSurface from being thrown away until the UI
782116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // thread can open another reference to it, if needed.
783116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    base::ScopedCFTypeRef<IOSurfaceRef> io_surface(IOSurfaceLookup(
784116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        IOSurfaceIDFromSurfaceHandle(params.surface_handle)));
785116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    BrowserThread::PostTask(BrowserThread::UI,
786116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                            FROM_HERE,
787116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                            base::Bind(HoldIOSurfaceReference, io_surface));
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
790116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // If delegated rendering is enabled, then immediately acknowledge this frame
791116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // on the IO thread instead of the UI thread. The UI thread will wait on the
792116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // GPU process. If the UI thread were to be responsible for acking swaps,
793116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // then there would be a cycle and a potential deadlock. Back-pressure from
794116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // the GPU is provided through the compositor's output surface.
795a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
796a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  ack_params.sync_point = 0;
797116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ack_params.renderer_id = 0;
798116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  Send(new AcceleratedSurfaceMsg_BufferPresented(params.route_id, ack_params));
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
800116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuProcessHost::OnProcessLaunched() {
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_TIMES("GPU.GPUProcessLaunchTime",
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      base::TimeTicks::Now() - init_start_time_);
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuProcessHost::OnProcessCrashed(int exit_code) {
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendOutstandingReplies();
8095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  RecordProcessCrash();
8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GpuDataManagerImpl::GetInstance()->ProcessCrashed(
811424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      process_->GetTerminationStatus(true /* known_dead */, NULL));
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuProcessHost::GpuProcessKind GpuProcessHost::kind() {
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return kind_;
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuProcessHost::ForceShutdown() {
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is only called on the IO thread so no race against the constructor
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for another GpuProcessHost.
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g_gpu_process_hosts[kind_] == this)
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_gpu_process_hosts[kind_] = NULL;
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process_->ForceShutdown();
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuProcessHost::BeginFrameSubscription(
8282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int surface_id,
8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::WeakPtr<RenderWidgetHostViewFrameSubscriber> subscriber) {
8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame_subscribers_[surface_id] = subscriber;
8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuProcessHost::EndFrameSubscription(int surface_id) {
8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame_subscribers_.erase(surface_id);
8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuProcessHost::LaunchGpuProcess(const std::string& channel_id) {
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!(gpu_enabled_ &&
839c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GpuDataManagerImpl::GetInstance()->ShouldUseSwiftShader()) &&
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !hardware_gpu_enabled_) {
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendOutstandingReplies();
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandLine::StringType gpu_launcher =
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser_command_line.GetSwitchValueNative(switches::kGpuLauncher);
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX)
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int child_flags = gpu_launcher.empty() ? ChildProcessHost::CHILD_ALLOW_SELF :
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           ChildProcessHost::CHILD_NORMAL;
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int child_flags = ChildProcessHost::CHILD_NORMAL;
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath exe_path = ChildProcessHost::GetChildPath(child_flags);
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (exe_path.empty())
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandLine* cmd_line = new CommandLine(exe_path);
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kGpuProcess);
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id);
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (kind_ == GPU_PROCESS_KIND_UNSANDBOXED)
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cmd_line->AppendSwitch(switches::kDisableGpuSandbox);
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Propagate relevant command line switches.
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* const kSwitchNames[] = {
8702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    switches::kDisableAcceleratedVideoDecode,
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switches::kDisableBreakpad,
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switches::kDisableGpuSandbox,
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switches::kDisableGpuWatchdog,
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switches::kDisableLogging,
8752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    switches::kDisableSeccompFilterSandbox,
876a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(ENABLE_WEBRTC)
877a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    switches::kDisableWebRtcHWEncoding,
878a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switches::kEnableLogging,
88090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    switches::kEnableShareGroupAsyncTextureUpload,
881116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(OS_CHROMEOS)
882116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    switches::kEnableVaapiAcceleratedVideoEncode,
883116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switches::kGpuStartupDialog,
885a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    switches::kGpuSandboxAllowSysVShm,
886a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    switches::kGpuSandboxFailuresFatal,
887116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    switches::kGpuSandboxStartEarly,
888cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    switches::kIgnoreResolutionLimitsForAcceleratedVideoDecode,
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switches::kLoggingLevel,
890116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    switches::kLowEndDeviceMode,
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switches::kNoSandbox,
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switches::kTestGLLib,
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switches::kTraceStartup,
894116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    switches::kTraceToConsole,
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switches::kV,
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switches::kVModule,
8972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_MACOSX)
8982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    switches::kEnableSandboxLogging,
8992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_AURA)
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switches::kUIPrioritizeInGpuProcess,
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
903a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(USE_OZONE)
904a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    switches::kOzonePlatform,
905a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif
906cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(USE_X11) && !defined(OS_CHROMEOS)
907cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    switches::kX11Display,
9085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cmd_line->CopySwitchesFrom(browser_command_line, kSwitchNames,
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             arraysize(kSwitchNames));
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cmd_line->CopySwitchesFrom(
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser_command_line, switches::kGpuSwitches, switches::kNumGpuSwitches);
9142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  cmd_line->CopySwitchesFrom(
9152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      browser_command_line, switches::kGLSwitchesCopiedFromGpuProcessHost,
9162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      switches::kGLSwitchesCopiedFromGpuProcessHostNumSwitches);
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetContentClient()->browser()->AppendExtraCommandLineSwitches(
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cmd_line, process_->GetData().id);
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GpuDataManagerImpl::GetInstance()->AppendGpuCommandLine(cmd_line);
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (cmd_line->HasSwitch(switches::kUseGL)) {
924c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    swiftshader_rendering_ =
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (cmd_line->GetSwitchValueASCII(switches::kUseGL) == "swiftshader");
9262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
928c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UMA_HISTOGRAM_BOOLEAN("GPU.GPU.GPUProcessSoftwareRendering",
929c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        swiftshader_rendering_);
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If specified, prepend a launcher program to the command line.
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!gpu_launcher.empty())
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cmd_line->PrependWrapper(gpu_launcher);
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process_->Launch(
936a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      new GpuSandboxedProcessLauncherDelegate(cmd_line,
937a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                              process_->GetHost()),
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cmd_line);
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process_launched_ = true;
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents",
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            LAUNCHED, GPU_PROCESS_LIFETIME_EVENT_MAX);
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuProcessHost::SendOutstandingReplies() {
9472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  valid_ = false;
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First send empty channel handles for all EstablishChannel requests.
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!channel_requests_.empty()) {
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EstablishChannelCallback callback = channel_requests_.front();
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel_requests_.pop();
95290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    callback.Run(IPC::ChannelHandle(), gpu::GPUInfo());
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
954c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
955c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while (!create_command_buffer_requests_.empty()) {
956c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CreateCommandBufferCallback callback =
957c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        create_command_buffer_requests_.front();
958c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    create_command_buffer_requests_.pop();
959116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    callback.Run(CREATE_COMMAND_BUFFER_FAILED_AND_CHANNEL_LOST);
960c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuProcessHost::BlockLiveOffscreenContexts() {
9642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::multiset<GURL>::iterator iter =
9652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           urls_with_live_offscreen_contexts_.begin();
9662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != urls_with_live_offscreen_contexts_.end(); ++iter) {
9672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs(
9682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        *iter, GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN);
9692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void GpuProcessHost::RecordProcessCrash() {
9735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Skip if a GPU process crash was already counted.
9745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (gpu_crash_recorded_)
9755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
9765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Maximum number of times the gpu process is allowed to crash in a session.
9785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Once this limit is reached, any request to launch the gpu process will
9795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // fail.
9805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const int kGpuMaxCrashCount = 3;
9815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Last time the GPU process crashed.
9835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  static base::Time last_gpu_crash_time;
9845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool disable_crash_limit = CommandLine::ForCurrentProcess()->HasSwitch(
9865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      switches::kDisableGpuProcessCrashLimit);
9875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Ending only acts as a failure if the GPU process was actually started and
9895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // was intended for actual rendering (and not just checking caps or other
9905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // options).
9915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (process_launched_ && kind_ == GPU_PROCESS_KIND_SANDBOXED) {
9925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    gpu_crash_recorded_ = true;
9935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (swiftshader_rendering_) {
9945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      UMA_HISTOGRAM_ENUMERATION("GPU.SwiftShaderLifetimeEvents",
9955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                DIED_FIRST_TIME + swiftshader_crash_count_,
9965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                GPU_PROCESS_LIFETIME_EVENT_MAX);
9975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (++swiftshader_crash_count_ >= kGpuMaxCrashCount &&
9995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          !disable_crash_limit) {
10005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        // SwiftShader is too unstable to use. Disable it for current session.
10015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        gpu_enabled_ = false;
10025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
10035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    } else {
10045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ++gpu_crash_count_;
10055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents",
10065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                std::min(DIED_FIRST_TIME + gpu_crash_count_,
10075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                         GPU_PROCESS_LIFETIME_EVENT_MAX - 1),
10085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                GPU_PROCESS_LIFETIME_EVENT_MAX);
10095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // Allow about 1 GPU crash per hour to be removed from the crash count,
10115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // so very occasional crashes won't eventually add up and prevent the
10125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // GPU process from launching.
10135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ++gpu_recent_crash_count_;
10145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::Time current_time = base::Time::Now();
10155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (crashed_before_) {
10165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        int hours_different = (current_time - last_gpu_crash_time).InHours();
10175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        gpu_recent_crash_count_ =
10185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            std::max(0, gpu_recent_crash_count_ - hours_different);
10195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
10205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      crashed_before_ = true;
10225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      last_gpu_crash_time = current_time;
10235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if ((gpu_recent_crash_count_ >= kGpuMaxCrashCount &&
10255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)           !disable_crash_limit) ||
10265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          !initialized_) {
10275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if !defined(OS_CHROMEOS)
10285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        // The gpu process is too unstable to use. Disable it for current
10295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        // session.
10305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        hardware_gpu_enabled_ = false;
10315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        GpuDataManagerImpl::GetInstance()->DisableHardwareAcceleration();
10325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
10335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
10345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
10355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
10365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
10375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string GpuProcessHost::GetShaderPrefixKey() {
10392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (shader_prefix_key_.empty()) {
104090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    gpu::GPUInfo info = GpuDataManagerImpl::GetInstance()->GetGPUInfo();
10412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string in_str = GetContentClient()->GetProduct() + "-" +
10432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        info.gl_vendor + "-" + info.gl_renderer + "-" +
10442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        info.driver_version + "-" + info.driver_vendor;
10452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::Base64Encode(base::SHA1HashString(in_str), &shader_prefix_key_);
10472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
10482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return shader_prefix_key_;
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuProcessHost::LoadedShader(const std::string& key,
10532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  const std::string& data) {
10542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string prefix = GetShaderPrefixKey();
10552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!key.compare(0, prefix.length(), prefix))
10562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Send(new GpuMsg_LoadedShader(data));
10572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void GpuProcessHost::CreateChannelCache(int32 client_id) {
10602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT0("gpu", "GpuProcessHost::CreateChannelCache");
10612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<ShaderDiskCache> cache =
10632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ShaderCacheFactory::GetInstance()->Get(client_id);
1064868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!cache.get())
10652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
10662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  cache->set_host_id(host_id_);
10682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_id_to_shader_cache_[client_id] = cache;
10702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuProcessHost::OnDestroyChannel(int32 client_id) {
10732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT0("gpu", "GpuProcessHost::OnDestroyChannel");
10742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_id_to_shader_cache_.erase(client_id);
10752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuProcessHost::OnCacheShader(int32 client_id,
10782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   const std::string& key,
10792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   const std::string& shader) {
10802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT0("gpu", "GpuProcessHost::OnCacheShader");
10812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClientIdToShaderCacheMap::iterator iter =
10822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      client_id_to_shader_cache_.find(client_id);
10832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If the cache doesn't exist then this is an off the record profile.
10842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (iter == client_id_to_shader_cache_.end())
10852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
10862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  iter->second->Cache(GetShaderPrefixKey() + ":" + key, shader);
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
1090