<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/gpu/gpu_process_host.h"

#include "base/base_switches.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/lazy_instance.h"
#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"
#include "content/browser/gpu/gpu_process_host_ui_shim.h"
#include "content/browser/gpu/gpu_surface_tracker.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/common/child_process_host_impl.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/gpu/gpu_child_thread.h"
#include "content/gpu/gpu_process.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/result_codes.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_switches.h"
#include "ui/gfx/gl/gl_context.h"
#include "ui/gfx/gl/gl_implementation.h"
#include "ui/gfx/gl/gl_switches.h"

#if defined(TOOLKIT_USES_GTK)
#include "ui/gfx/gtk_native_view_id_manager.h"
#endif

#if defined(OS_WIN) && !defined(USE_AURA)
#include "ui/gfx/surface/accelerated_surface_win.h"
#endif

using content::BrowserThread;
using content::ChildProcessHost;

bool GpuProcessHost::gpu_enabled_ = true;
bool GpuProcessHost::hardware_gpu_enabled_ = true;

namespace {

enum GPUProcessLifetimeEvent {
  LAUNCHED,
  DIED_FIRST_TIME,
  DIED_SECOND_TIME,
  DIED_THIRD_TIME,
  DIED_FOURTH_TIME,
  GPU_PROCESS_LIFETIME_EVENT_MAX
};

// A global map from GPU process host ID to GpuProcessHost.
static base::LazyInstance<IDMap<GpuProcessHost> > g_hosts_by_id =
    LAZY_INSTANCE_INITIALIZER;

// Number of times the gpu process has crashed in the current browser session.
static int g_gpu_crash_count = 0;
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_USES_GTK)

void ReleasePermanentXIDDispatcher(gfx::PluginWindowHandle surface) {
  GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance();
  manager->ReleasePermanentXID(surface);
}

#endif

void SendGpuProcessMessage(GpuProcessHost::GpuProcessKind kind,
                           content::CauseForGpuLaunch cause,
                           IPC::Message* message) {
  GpuProcessHost* host = GpuProcessHost::Get(kind, cause);
  if (host) {
    host->Send(message);
  } else {
    delete message;
  }
}

void AcceleratedSurfaceBuffersSwappedCompleted(int host_id,
                                               int route_id,
                                               bool alive) {
  if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
    GpuProcessHost* host = GpuProcessHost::FromID(host_id);
    if (host) {
      if (alive)
        host->Send(new AcceleratedSurfaceMsg_BuffersSwappedACK(route_id));
      else {
        host->ForceShutdown();
      }
    }
  } else {
    BrowserThread::PostTask(
      BrowserThread::IO,
      FROM_HERE,
      base::Bind(&AcceleratedSurfaceBuffersSwappedCompleted,
                 host_id,
                 route_id,
                 alive));
  }
}

}  // anonymous namespace

#if defined(TOOLKIT_USES_GTK)
// Used to put a lock on surfaces so that the window to which the GPU
// process is drawing to doesn't disappear while it is drawing when
// a tab is closed.
class GpuProcessHost::SurfaceRef {
 public:
  explicit SurfaceRef(gfx::PluginWindowHandle surface);
  ~SurfaceRef();
 private:
  gfx::PluginWindowHandle surface_;
};

GpuProcessHost::SurfaceRef::SurfaceRef(gfx::PluginWindowHandle surface)
    : surface_(surface) {
  GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance();
  if (!manager->AddRefPermanentXID(surface_)) {
    LOG(ERROR) << "Surface " << surface << " cannot be referenced.";
  }
}

GpuProcessHost::SurfaceRef::~SurfaceRef() {
  BrowserThread::PostTask(BrowserThread::UI,
                          FROM_HERE,
                          base::Bind(&ReleasePermanentXIDDispatcher, surface_));
}
#endif  // defined(TOOLKIT_USES_GTK)

// This class creates a GPU thread (instead of a GPU process), when running
// with --in-process-gpu or --single-process.
class GpuMainThread : public base::Thread {
 public:
  explicit GpuMainThread(const std::string& channel_id)
      : base::Thread("Chrome_InProcGpuThread"),
        channel_id_(channel_id),
        gpu_process_(NULL),
        child_thread_(NULL) {
  }

  ~GpuMainThread() {
    Stop();
  }

 protected:
  virtual void Init() {
    if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) ||
        CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU)) {
      child_thread_ = new GpuChildThread(channel_id_);
    } else {
      gpu_process_ = new GpuProcess();
      // The process object takes ownership of the thread object, so do not
      // save and delete the pointer.
      gpu_process_->set_main_thread(new GpuChildThread(channel_id_));
    }
  }

  virtual void CleanUp() {
    delete gpu_process_;
    if (child_thread_)
      delete child_thread_;
  }

 private:<commit_msg>Removing --in-process-gpu from the set of flags that prevents creation of a GpuChildThread. <commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/gpu/gpu_process_host.h"

#include "base/base_switches.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/lazy_instance.h"
#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"
#include "content/browser/gpu/gpu_process_host_ui_shim.h"
#include "content/browser/gpu/gpu_surface_tracker.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/common/child_process_host_impl.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/gpu/gpu_child_thread.h"
#include "content/gpu/gpu_process.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/result_codes.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_switches.h"
#include "ui/gfx/gl/gl_context.h"
#include "ui/gfx/gl/gl_implementation.h"
#include "ui/gfx/gl/gl_switches.h"

#if defined(TOOLKIT_USES_GTK)
#include "ui/gfx/gtk_native_view_id_manager.h"
#endif

#if defined(OS_WIN) && !defined(USE_AURA)
#include "ui/gfx/surface/accelerated_surface_win.h"
#endif

using content::BrowserThread;
using content::ChildProcessHost;

bool GpuProcessHost::gpu_enabled_ = true;
bool GpuProcessHost::hardware_gpu_enabled_ = true;

namespace {

enum GPUProcessLifetimeEvent {
  LAUNCHED,
  DIED_FIRST_TIME,
  DIED_SECOND_TIME,
  DIED_THIRD_TIME,
  DIED_FOURTH_TIME,
  GPU_PROCESS_LIFETIME_EVENT_MAX
};

// A global map from GPU process host ID to GpuProcessHost.
static base::LazyInstance<IDMap<GpuProcessHost> > g_hosts_by_id =
    LAZY_INSTANCE_INITIALIZER;

// Number of times the gpu process has crashed in the current browser session.
static int g_gpu_crash_count = 0;
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_USES_GTK)

void ReleasePermanentXIDDispatcher(gfx::PluginWindowHandle surface) {
  GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance();
  manager->ReleasePermanentXID(surface);
}

#endif

void SendGpuProcessMessage(GpuProcessHost::GpuProcessKind kind,
                           content::CauseForGpuLaunch cause,
                           IPC::Message* message) {
  GpuProcessHost* host = GpuProcessHost::Get(kind, cause);
  if (host) {
    host->Send(message);
  } else {
    delete message;
  }
}

void AcceleratedSurfaceBuffersSwappedCompleted(int host_id,
                                               int route_id,
                                               bool alive) {
  if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
    GpuProcessHost* host = GpuProcessHost::FromID(host_id);
    if (host) {
      if (alive)
        host->Send(new AcceleratedSurfaceMsg_BuffersSwappedACK(route_id));
      else {
        host->ForceShutdown();
      }
    }
  } else {
    BrowserThread::PostTask(
      BrowserThread::IO,
      FROM_HERE,
      base::Bind(&AcceleratedSurfaceBuffersSwappedCompleted,
                 host_id,
                 route_id,
                 alive));
  }
}

}  // anonymous namespace

#if defined(TOOLKIT_USES_GTK)
// Used to put a lock on surfaces so that the window to which the GPU
// process is drawing to doesn't disappear while it is drawing when
// a tab is closed.
class GpuProcessHost::SurfaceRef {
 public:
  explicit SurfaceRef(gfx::PluginWindowHandle surface);
  ~SurfaceRef();
 private:
  gfx::PluginWindowHandle surface_;
};

GpuProcessHost::SurfaceRef::SurfaceRef(gfx::PluginWindowHandle surface)
    : surface_(surface) {
  GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance();
  if (!manager->AddRefPermanentXID(surface_)) {
    LOG(ERROR) << "Surface " << surface << " cannot be referenced.";
  }
}

GpuProcessHost::SurfaceRef::~SurfaceRef() {
  BrowserThread::PostTask(BrowserThread::UI,
                          FROM_HERE,
                          base::Bind(&ReleasePermanentXIDDispatcher, surface_));
}
#endif  // defined(TOOLKIT_USES_GTK)

// This class creates a GPU thread (instead of a GPU process), when running
// with --in-process-gpu or --single-process.
class GpuMainThread : public base::Thread {
 public:
  explicit GpuMainThread(const std::string& channel_id)
      : base::Thread("Chrome_InProcGpuThread"),
        channel_id_(channel_id),
        gpu_process_(NULL),
        child_thread_(NULL) {
  }

  ~GpuMainThread() {
    Stop();
  }

 protected:
  virtual void Init() {
    if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess)) {
      child_thread_ = new GpuChildThread(channel_id_);
    } else {
      gpu_process_ = new GpuProcess();
      // The process object takes ownership of the thread object, so do not
      // save and delete the pointer.
      gpu_process_->set_main_thread(new GpuChildThread(channel_id_));
    }
  }

  virtual void CleanUp() {
    delete gpu_process_;
    if (child_thread_)
      delete child_thread_;
  }

 private:
{'fraction_non_alphanumeric': 0.10715216824541583, 'fraction_numerical': 0.0013904579820978535, 'mean_word_length': 3.934819897084048, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 22, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2874708', 'n_tokens_mistral': 3760, 'n_tokens_neox': 3709, 'n_words': 787}