| Index: content/browser/gpu/gpu_process_host.cc
|
| ===================================================================
|
| --- content/browser/gpu/gpu_process_host.cc (revision 174988)
|
| +++ content/browser/gpu/gpu_process_host.cc (working copy)
|
| @@ -12,7 +12,6 @@
|
| #include "base/memory/ref_counted.h"
|
| #include "base/metrics/histogram.h"
|
| #include "base/process_util.h"
|
| -#include "base/string_piece.h"
|
| #include "base/threading/thread.h"
|
| #include "content/browser/browser_child_process_host_impl.h"
|
| #include "content/browser/gpu/gpu_data_manager_impl.h"
|
| @@ -34,8 +33,6 @@
|
| #include "gpu/command_buffer/service/gpu_switches.h"
|
| #include "ipc/ipc_channel_handle.h"
|
| #include "ipc/ipc_switches.h"
|
| -#include "ui/gl/gl_context.h"
|
| -#include "ui/gl/gl_implementation.h"
|
| #include "ui/gl/gl_switches.h"
|
|
|
| #if defined(TOOLKIT_GTK)
|
| @@ -64,22 +61,8 @@
|
|
|
| // Indexed by GpuProcessKind. There is one of each kind maximum. This array may
|
| // only be accessed from the IO thread.
|
| -static GpuProcessHost *g_gpu_process_hosts[
|
| - GpuProcessHost::GPU_PROCESS_KIND_COUNT];
|
| +GpuProcessHost* g_gpu_process_hosts[GpuProcessHost::GPU_PROCESS_KIND_COUNT];
|
|
|
| -// Number of times the gpu process has crashed in the current browser session.
|
| -static int g_gpu_crash_count = 0;
|
| -static int g_gpu_recent_crash_count = 0;
|
| -static double g_last_gpu_crash_time;
|
| -static bool g_crashed_before = false;
|
| -static int g_gpu_software_crash_count = 0;
|
| -
|
| -// Maximum number of times the gpu process is allowed to crash in a session.
|
| -// Once this limit is reached, any request to launch the gpu process will fail.
|
| -static const int kGpuMaxCrashCount = 3;
|
| -
|
| -int g_last_host_id = 0;
|
| -
|
| #if defined(TOOLKIT_GTK)
|
|
|
| void ReleasePermanentXIDDispatcher(gfx::PluginWindowHandle surface) {
|
| @@ -121,8 +104,8 @@
|
| if (alive) {
|
| AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
|
| ack_params.sync_point = 0;
|
| - host->Send(new AcceleratedSurfaceMsg_BufferPresented(
|
| - route_id, ack_params));
|
| + host->Send(
|
| + new AcceleratedSurfaceMsg_BufferPresented(route_id, ack_params));
|
| } else {
|
| host->ForceShutdown();
|
| }
|
| @@ -131,7 +114,7 @@
|
|
|
| #if defined(OS_WIN)
|
| // This sends a ViewMsg_SwapBuffers_ACK directly to the renderer process
|
| -// (RenderWidget). This path is currently not used with the threaded compositor.
|
| +// (RenderWidget).
|
| void AcceleratedSurfaceBuffersSwappedCompletedForRenderer(
|
| int surface_id,
|
| base::TimeTicks timebase,
|
| @@ -203,12 +186,12 @@
|
| child_thread_(NULL) {
|
| }
|
|
|
| - ~GpuMainThread() {
|
| + virtual ~GpuMainThread() {
|
| Stop();
|
| }
|
|
|
| protected:
|
| - virtual void Init() {
|
| + virtual void Init() OVERRIDE {
|
| if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess)) {
|
| child_thread_ = new GpuChildThread(channel_id_);
|
| } else {
|
| @@ -219,7 +202,7 @@
|
| }
|
| }
|
|
|
| - virtual void CleanUp() {
|
| + virtual void CleanUp() OVERRIDE {
|
| delete gpu_process_;
|
| if (child_thread_)
|
| delete child_thread_;
|
| @@ -235,7 +218,7 @@
|
| };
|
|
|
| // static
|
| -bool GpuProcessHost::HostIsValid(GpuProcessHost* host) {
|
| +bool GpuProcessHost::ValidateHost(GpuProcessHost* host) {
|
| if (!host)
|
| return false;
|
|
|
| @@ -264,14 +247,15 @@
|
| if (!gpu_data_manager->GpuAccessAllowed())
|
| return NULL;
|
|
|
| - if (g_gpu_process_hosts[kind] && HostIsValid(g_gpu_process_hosts[kind]))
|
| + if (g_gpu_process_hosts[kind] && ValidateHost(g_gpu_process_hosts[kind]))
|
| return g_gpu_process_hosts[kind];
|
|
|
| if (cause == CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH)
|
| return NULL;
|
|
|
| + static int last_host_id = 0;
|
| int host_id;
|
| - host_id = ++g_last_host_id;
|
| + host_id = ++last_host_id;
|
|
|
| UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLaunchCause",
|
| cause,
|
| @@ -296,9 +280,9 @@
|
| return;
|
| }
|
| std::list<base::ProcessHandle> handles;
|
| - for (int i = 0; i < GPU_PROCESS_KIND_COUNT; ++i) {
|
| + for (size_t i = 0; i < arraysize(g_gpu_process_hosts); ++i) {
|
| GpuProcessHost* host = g_gpu_process_hosts[i];
|
| - if (host && HostIsValid(host))
|
| + if (host && ValidateHost(host))
|
| handles.push_back(host->process_->GetHandle());
|
| }
|
| BrowserThread::PostTask(
|
| @@ -325,7 +309,7 @@
|
|
|
| for (int i = 0; i < GPU_PROCESS_KIND_COUNT; ++i) {
|
| GpuProcessHost* host = g_gpu_process_hosts[i];
|
| - if (host && host->host_id_ == host_id && HostIsValid(host))
|
| + if (host && host->host_id_ == host_id && ValidateHost(host))
|
| return host;
|
| }
|
|
|
| @@ -340,8 +324,9 @@
|
| kind_(kind),
|
| process_launched_(false) {
|
| if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) ||
|
| - CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU))
|
| + CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU)) {
|
| in_process_ = true;
|
| + }
|
|
|
| // If the 'single GPU process' policy ever changes, we still want to maintain
|
| // it for 'gpu thread' mode and only create one instance of host and thread.
|
| @@ -366,46 +351,55 @@
|
| DCHECK(CalledOnValidThread());
|
|
|
| SendOutstandingReplies();
|
| +
|
| + // Maximum number of times the gpu process is allowed to crash in a session.
|
| + // Once this limit is reached, any request to launch the gpu process will
|
| + // fail.
|
| + const int kGpuMaxCrashCount = 3;
|
| +
|
| + // Number of times the gpu process has crashed in the current browser session.
|
| + static int gpu_crash_count = 0;
|
| + static int gpu_recent_crash_count = 0;
|
| + static base::Time last_gpu_crash_time;
|
| + static bool crashed_before = false;
|
| + static int gpu_software_crash_count = 0;
|
| +
|
| // Ending only acts as a failure if the GPU process was actually started and
|
| // was intended for actual rendering (and not just checking caps or other
|
| // options).
|
| if (process_launched_ && kind_ == GPU_PROCESS_KIND_SANDBOXED) {
|
| if (software_rendering_) {
|
| UMA_HISTOGRAM_ENUMERATION("GPU.SoftwareRendererLifetimeEvents",
|
| - DIED_FIRST_TIME + g_gpu_software_crash_count,
|
| + DIED_FIRST_TIME + gpu_software_crash_count,
|
| GPU_PROCESS_LIFETIME_EVENT_MAX);
|
|
|
| - if (++g_gpu_software_crash_count >= kGpuMaxCrashCount) {
|
| + if (++gpu_software_crash_count >= kGpuMaxCrashCount) {
|
| // The software renderer is too unstable to use. Disable it for current
|
| // session.
|
| gpu_enabled_ = false;
|
| }
|
| } else {
|
| - ++g_gpu_crash_count;
|
| + ++gpu_crash_count;
|
| UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents",
|
| - std::min(DIED_FIRST_TIME + g_gpu_crash_count,
|
| + std::min(DIED_FIRST_TIME + gpu_crash_count,
|
| GPU_PROCESS_LIFETIME_EVENT_MAX - 1),
|
| GPU_PROCESS_LIFETIME_EVENT_MAX);
|
|
|
| - /*
|
| - * Allow about 1 GPU crash per hour to be removed from the crash count,
|
| - * so very occasional crashes won't eventually add up and prevent the
|
| - * GPU process from launching.
|
| - */
|
| - ++g_gpu_recent_crash_count;
|
| + // Allow about 1 GPU crash per hour to be removed from the crash count,
|
| + // so very occasional crashes won't eventually add up and prevent the
|
| + // GPU process from launching.
|
| + ++gpu_recent_crash_count;
|
| base::Time current_time = base::Time::Now();
|
| - if (g_crashed_before) {
|
| - base::Time last_crash_time =
|
| - base::Time::FromDoubleT(g_last_gpu_crash_time);
|
| - int hours_different = (current_time - last_crash_time).InHours();
|
| - g_gpu_recent_crash_count = std::max(0,
|
| - g_gpu_recent_crash_count - hours_different);
|
| + if (crashed_before) {
|
| + int hours_different = (current_time - last_gpu_crash_time).InHours();
|
| + gpu_recent_crash_count =
|
| + std::max(0, gpu_recent_crash_count - hours_different);
|
| }
|
|
|
| - g_crashed_before = true;
|
| - g_last_gpu_crash_time = current_time.ToDoubleT();
|
| + crashed_before = true;
|
| + last_gpu_crash_time = current_time;
|
|
|
| - if (g_gpu_recent_crash_count >= kGpuMaxCrashCount) {
|
| + if (gpu_recent_crash_count >= kGpuMaxCrashCount) {
|
| #if !defined(OS_CHROMEOS)
|
| // The gpu process is too unstable to use. Disable it for current
|
| // session.
|
| @@ -478,20 +472,8 @@
|
| switches::kDisableGpuWatchdog);
|
|
|
| in_process_gpu_thread_.reset(new GpuMainThread(channel_id));
|
| + in_process_gpu_thread_->Start();
|
|
|
| - base::Thread::Options options;
|
| -#if defined(OS_WIN)
|
| - // On Windows the GPU thread needs to pump the compositor child window's
|
| - // message loop. TODO(apatrick): make this an IO thread if / when we get rid
|
| - // of this child window. Unfortunately it might always be necessary for
|
| - // Windows XP because we cannot share the backing store textures between
|
| - // processes.
|
| - options.message_loop_type = MessageLoop::TYPE_UI;
|
| -#else
|
| - options.message_loop_type = MessageLoop::TYPE_IO;
|
| -#endif
|
| - in_process_gpu_thread_->StartWithOptions(options);
|
| -
|
| OnProcessLaunched(); // Fake a callback that the process is ready.
|
| } else if (!LaunchGpuProcess(channel_id)) {
|
| return false;
|
| @@ -582,17 +564,14 @@
|
|
|
| // If GPU features are already blacklisted, no need to establish the channel.
|
| if (!GpuDataManagerImpl::GetInstance()->GpuAccessAllowed()) {
|
| - EstablishChannelError(
|
| - callback, IPC::ChannelHandle(), base::kNullProcessHandle, GPUInfo());
|
| + callback.Run(IPC::ChannelHandle(), GPUInfo());
|
| return;
|
| }
|
|
|
| if (Send(new GpuMsg_EstablishChannel(client_id, share_context))) {
|
| channel_requests_.push(callback);
|
| } else {
|
| - EstablishChannelError(
|
| - callback, IPC::ChannelHandle(),
|
| - base::kNullProcessHandle, GPUInfo());
|
| + callback.Run(IPC::ChannelHandle(), GPUInfo());
|
| }
|
| }
|
|
|
| @@ -627,15 +606,14 @@
|
| surface_refs_.insert(std::make_pair(surface_id, surface_ref));
|
| #endif
|
| } else {
|
| - CreateCommandBufferError(callback, MSG_ROUTING_NONE);
|
| + callback.Run(MSG_ROUTING_NONE);
|
| }
|
| }
|
|
|
| -void GpuProcessHost::CreateImage(
|
| - gfx::PluginWindowHandle window,
|
| - int client_id,
|
| - int image_id,
|
| - const CreateImageCallback& callback) {
|
| +void GpuProcessHost::CreateImage(gfx::PluginWindowHandle window,
|
| + int client_id,
|
| + int image_id,
|
| + const CreateImageCallback& callback) {
|
| TRACE_EVENT0("gpu", "GpuProcessHostUIShim::CreateImage");
|
|
|
| DCHECK(CalledOnValidThread());
|
| @@ -643,14 +621,13 @@
|
| if (Send(new GpuMsg_CreateImage(window, client_id, image_id))) {
|
| create_image_requests_.push(callback);
|
| } else {
|
| - CreateImageError(callback, gfx::Size());
|
| + callback.Run(gfx::Size());
|
| }
|
| }
|
|
|
| -void GpuProcessHost::DeleteImage(
|
| - int client_id,
|
| - int image_id,
|
| - int sync_point) {
|
| +void GpuProcessHost::DeleteImage(int client_id,
|
| + int image_id,
|
| + int sync_point) {
|
| TRACE_EVENT0("gpu", "GpuProcessHostUIShim::DeleteImage");
|
|
|
| DCHECK(CalledOnValidThread());
|
| @@ -674,10 +651,7 @@
|
| if (!channel_handle.name.empty() &&
|
| !GpuDataManagerImpl::GetInstance()->GpuAccessAllowed()) {
|
| Send(new GpuMsg_CloseChannel(channel_handle));
|
| - EstablishChannelError(callback,
|
| - IPC::ChannelHandle(),
|
| - base::kNullProcessHandle,
|
| - GPUInfo());
|
| + callback.Run(IPC::ChannelHandle(), GPUInfo());
|
| RouteOnUIThread(GpuHostMsg_OnLogMessage(
|
| logging::LOG_WARNING,
|
| "WARNING",
|
| @@ -692,15 +666,13 @@
|
| void GpuProcessHost::OnCommandBufferCreated(const int32 route_id) {
|
| TRACE_EVENT0("gpu", "GpuProcessHostUIShim::OnCommandBufferCreated");
|
|
|
| - if (!create_command_buffer_requests_.empty()) {
|
| - CreateCommandBufferCallback callback =
|
| - create_command_buffer_requests_.front();
|
| - create_command_buffer_requests_.pop();
|
| - if (route_id == MSG_ROUTING_NONE)
|
| - CreateCommandBufferError(callback, route_id);
|
| - else
|
| - callback.Run(route_id);
|
| - }
|
| + if (create_command_buffer_requests_.empty())
|
| + return;
|
| +
|
| + CreateCommandBufferCallback callback =
|
| + create_command_buffer_requests_.front();
|
| + create_command_buffer_requests_.pop();
|
| + callback.Run(route_id);
|
| }
|
|
|
| void GpuProcessHost::OnDestroyCommandBuffer(int32 surface_id) {
|
| @@ -716,15 +688,15 @@
|
| void GpuProcessHost::OnImageCreated(const gfx::Size size) {
|
| TRACE_EVENT0("gpu", "GpuProcessHost::OnImageCreated");
|
|
|
| - if (!create_image_requests_.empty()) {
|
| - CreateImageCallback callback = create_image_requests_.front();
|
| - create_image_requests_.pop();
|
| - callback.Run(size);
|
| - }
|
| + if (!create_image_requests_.empty())
|
| + return;
|
| +
|
| + CreateImageCallback callback = create_image_requests_.front();
|
| + create_image_requests_.pop();
|
| + callback.Run(size);
|
| }
|
|
|
| -void GpuProcessHost::OnDidCreateOffscreenContext(
|
| - const GURL& url) {
|
| +void GpuProcessHost::OnDidCreateOffscreenContext(const GURL& url) {
|
| urls_with_live_offscreen_contexts_.insert(url);
|
| }
|
|
|
| @@ -747,10 +719,7 @@
|
| return;
|
| }
|
|
|
| - // Initialization only needed because compiler is stupid.
|
| - GpuDataManagerImpl::DomainGuilt guilt =
|
| - GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN;
|
| -
|
| + GpuDataManagerImpl::DomainGuilt guilt;
|
| switch (reason) {
|
| case gpu::error::kGuilty:
|
| guilt = GpuDataManagerImpl::DOMAIN_GUILT_KNOWN;
|
| @@ -760,14 +729,15 @@
|
| break;
|
| case gpu::error::kInnocent:
|
| return;
|
| + default:
|
| + NOTREACHED();
|
| + return;
|
| }
|
|
|
| - GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs(
|
| - url, guilt);
|
| + GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs(url, guilt);
|
| }
|
|
|
| -void GpuProcessHost::OnDidDestroyOffscreenContext(
|
| - const GURL& url) {
|
| +void GpuProcessHost::OnDidDestroyOffscreenContext(const GURL& url) {
|
| urls_with_live_offscreen_contexts_.erase(url);
|
| }
|
|
|
| @@ -987,37 +957,37 @@
|
|
|
| // Propagate relevant command line switches.
|
| static const char* const kSwitchNames[] = {
|
| + switches::kCrashOnGpuHang,
|
| + switches::kDisableAcceleratedVideoDecode,
|
| switches::kDisableBreakpad,
|
| switches::kDisableGLMultisampling,
|
| switches::kDisableGpuSandbox,
|
| - switches::kReduceGpuSandbox,
|
| - switches::kDisableSeccompFilterSandbox,
|
| - switches::kEnableGpuSandbox,
|
| switches::kDisableGpuVsync,
|
| switches::kDisableGpuWatchdog,
|
| switches::kDisableImageTransportSurface,
|
| - switches::kDisableAcceleratedVideoDecode,
|
| switches::kDisableLogging,
|
| + switches::kDisableSeccompFilterSandbox,
|
| + switches::kEnableGpuSandbox,
|
| switches::kEnableGPUServiceLogging,
|
| switches::kEnableLogging,
|
| -#if defined(OS_MACOSX)
|
| - switches::kEnableSandboxLogging,
|
| -#endif
|
| + switches::kEnableUIReleaseFrontSurface,
|
| + switches::kEnableVirtualGLContexts,
|
| switches::kGpuNoContextLost,
|
| switches::kGpuStartupDialog,
|
| switches::kGpuSwitching,
|
| switches::kLoggingLevel,
|
| switches::kNoSandbox,
|
| + switches::kReduceGpuSandbox,
|
| switches::kTestGLLib,
|
| switches::kTraceStartup,
|
| switches::kV,
|
| switches::kVModule,
|
| - switches::kEnableUIReleaseFrontSurface,
|
| +#if defined(OS_MACOSX)
|
| + switches::kEnableSandboxLogging,
|
| +#endif
|
| #if defined(USE_AURA)
|
| switches::kUIPrioritizeInGpuProcess,
|
| #endif
|
| - switches::kCrashOnGpuHang,
|
| - switches::kEnableVirtualGLContexts,
|
| };
|
| cmd_line->CopySwitchesFrom(browser_command_line, kSwitchNames,
|
| arraysize(kSwitchNames));
|
| @@ -1029,15 +999,16 @@
|
|
|
| GpuDataManagerImpl::GetInstance()->AppendGpuCommandLine(cmd_line);
|
|
|
| - if (cmd_line->HasSwitch(switches::kUseGL))
|
| + if (cmd_line->HasSwitch(switches::kUseGL)) {
|
| software_rendering_ =
|
| (cmd_line->GetSwitchValueASCII(switches::kUseGL) == "swiftshader");
|
| + }
|
|
|
| UMA_HISTOGRAM_BOOLEAN("GPU.GPUProcessSoftwareRendering", software_rendering_);
|
|
|
| #if defined(OS_WIN)
|
| - // Make GoogleDesktopNetwork3.dll think that this is a renderer process so
|
| - // it unloads itself. http://crbug/129884
|
| + // Make GoogleDesktopNetwork3.dll think that the GPU process is a renderer
|
| + // process so the DLL unloads itself. http://crbug/129884
|
| cmd_line->AppendSwitchASCII("ignored", " --type=renderer ");
|
| #endif
|
|
|
| @@ -1049,7 +1020,7 @@
|
| #if defined(OS_WIN)
|
| FilePath(),
|
| #elif defined(OS_POSIX)
|
| - false, // Never use the zygote (GPU plugin can't be sandboxed).
|
| + false,
|
| base::EnvironmentVector(),
|
| #endif
|
| cmd_line);
|
| @@ -1065,31 +1036,10 @@
|
| while (!channel_requests_.empty()) {
|
| EstablishChannelCallback callback = channel_requests_.front();
|
| channel_requests_.pop();
|
| - EstablishChannelError(callback,
|
| - IPC::ChannelHandle(),
|
| - base::kNullProcessHandle,
|
| - GPUInfo());
|
| + callback.Run(IPC::ChannelHandle(), GPUInfo());
|
| }
|
| }
|
|
|
| -void GpuProcessHost::EstablishChannelError(
|
| - const EstablishChannelCallback& callback,
|
| - const IPC::ChannelHandle& channel_handle,
|
| - base::ProcessHandle renderer_process_for_gpu,
|
| - const GPUInfo& gpu_info) {
|
| - callback.Run(channel_handle, gpu_info);
|
| -}
|
| -
|
| -void GpuProcessHost::CreateCommandBufferError(
|
| - const CreateCommandBufferCallback& callback, int32 route_id) {
|
| - callback.Run(route_id);
|
| -}
|
| -
|
| -void GpuProcessHost::CreateImageError(
|
| - const CreateImageCallback& callback, const gfx::Size size) {
|
| - callback.Run(size);
|
| -}
|
| -
|
| void GpuProcessHost::BlockLiveOffscreenContexts() {
|
| for (std::multiset<GURL>::iterator iter =
|
| urls_with_live_offscreen_contexts_.begin();
|
|
|