summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/app/chrome_dll_main.cc3
-rw-r--r--chrome/browser/child_process_launcher.cc36
-rw-r--r--chrome/browser/child_process_launcher.h1
-rw-r--r--chrome/browser/gpu_process_host.cc13
-rw-r--r--chrome/browser/gpu_process_host.h4
-rw-r--r--chrome/browser/nacl_process_host.cc3
-rw-r--r--chrome/browser/plugin_process_host.cc14
-rw-r--r--chrome/browser/renderer_host/backing_store_glx.h74
-rw-r--r--chrome/browser/renderer_host/backing_store_manager_glx.cc57
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.cc28
-rw-r--r--chrome/browser/renderer_host/gpu_view_host.cc5
-rw-r--r--chrome/browser/renderer_host/gpu_view_host.h4
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_gtk.cc30
-rw-r--r--chrome/browser/utility_process_host.cc3
-rw-r--r--chrome/browser/worker_host/worker_process_host.cc3
-rwxr-xr-xchrome/chrome.gyp40
-rw-r--r--chrome/common/child_process_host.cc8
-rw-r--r--chrome/common/child_process_host.h16
-rw-r--r--chrome/common/chrome_switches.cc4
-rw-r--r--chrome/common/chrome_switches.h1
-rw-r--r--chrome/common/gpu_messages.h2
-rw-r--r--chrome/common/gpu_messages_internal.h2
-rw-r--r--chrome/common/gpu_native_window_handle.h41
-rw-r--r--chrome/gpu/gpu_backing_store_glx.cc (renamed from chrome/browser/renderer_host/backing_store_gl.cc)151
-rw-r--r--chrome/gpu/gpu_backing_store_glx.h65
-rw-r--r--chrome/gpu/gpu_backing_store_glx_context.cc54
-rw-r--r--chrome/gpu/gpu_backing_store_glx_context.h (renamed from chrome/browser/renderer_host/backing_store_manager_glx.h)26
-rw-r--r--chrome/gpu/gpu_backing_store_win.cc (renamed from chrome/gpu/gpu_backing_store.cc)28
-rw-r--r--chrome/gpu/gpu_backing_store_win.h (renamed from chrome/gpu/gpu_backing_store.h)20
-rw-r--r--chrome/gpu/gpu_main.cc6
-rw-r--r--chrome/gpu/gpu_thread.cc26
-rw-r--r--chrome/gpu/gpu_thread.h21
-rw-r--r--chrome/gpu/gpu_view_win.cc10
-rw-r--r--chrome/gpu/gpu_view_win.h10
-rw-r--r--chrome/gpu/gpu_view_x.cc96
-rw-r--r--chrome/gpu/gpu_view_x.h58
-rw-r--r--chrome/gpu/x_util.cc11
-rw-r--r--chrome/gpu/x_util.h45
38 files changed, 654 insertions, 365 deletions
diff --git a/chrome/app/chrome_dll_main.cc b/chrome/app/chrome_dll_main.cc
index a43f0e2..1e3cb83 100644
--- a/chrome/app/chrome_dll_main.cc
+++ b/chrome/app/chrome_dll_main.cc
@@ -255,7 +255,8 @@ static void AdjustLinuxOOMScore(const std::string& process_type) {
if (process_type == switches::kPluginProcess) {
score = kPluginScore;
} else if (process_type == switches::kUtilityProcess ||
- process_type == switches::kWorkerProcess) {
+ process_type == switches::kWorkerProcess ||
+ process_type == switches::kGpuProcess) {
score = kMiscScore;
} else if (process_type == switches::kProfileImportProcess) {
NOTIMPLEMENTED();
diff --git a/chrome/browser/child_process_launcher.cc b/chrome/browser/child_process_launcher.cc
index d290e36..ff555fe 100644
--- a/chrome/browser/child_process_launcher.cc
+++ b/chrome/browser/child_process_launcher.cc
@@ -49,6 +49,7 @@ class ChildProcessLauncher::Context
#if defined(OS_WIN)
const FilePath& exposed_dir,
#elif defined(OS_POSIX)
+ bool use_zygote,
const base::environment_vector& environ,
int ipcfd,
#endif
@@ -66,6 +67,7 @@ class ChildProcessLauncher::Context
#if defined(OS_WIN)
exposed_dir,
#elif defined(POSIX)
+ use_zygote,
environ,
ipcfd,
#endif
@@ -91,6 +93,7 @@ class ChildProcessLauncher::Context
#if defined(OS_WIN)
const FilePath& exposed_dir,
#elif defined(OS_POSIX)
+ bool use_zygote,
const base::environment_vector& env,
int ipcfd,
#endif
@@ -102,22 +105,7 @@ class ChildProcessLauncher::Context
#elif defined(OS_POSIX)
#if defined(OS_LINUX)
- bool zygote = false;
- // On Linux, normally spawn renderer processes with zygotes. We can't do
- // this when we're spawning child processes through an external program
- // (i.e. there is a command prefix) like GDB so fall through to the POSIX
- // case then.
- bool is_renderer = cmd_line->GetSwitchValueASCII(switches::kProcessType) ==
- switches::kRendererProcess;
- bool is_extension = cmd_line->GetSwitchValueASCII(switches::kProcessType) ==
- switches::kExtensionProcess;
- bool is_plugin = cmd_line->GetSwitchValueASCII(switches::kProcessType) ==
- switches::kPluginProcess;
- if ((is_renderer || is_extension) &&
- !CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kRendererCmdPrefix)) {
- zygote = true;
-
+ if (use_zygote) {
base::GlobalDescriptors::Mapping mapping;
mapping.push_back(std::pair<uint32_t, int>(kPrimaryIPCChannel, ipcfd));
const int crash_signal_fd =
@@ -127,9 +115,8 @@ class ChildProcessLauncher::Context
crash_signal_fd));
}
handle = Singleton<ZygoteHost>()->ForkRenderer(cmd_line->argv(), mapping);
- }
-
- if (!zygote)
+ } else
+ // Fall through to the normal posix case below when we're not zygoting.
#endif
{
base::file_handle_mapping_vector fds_to_map;
@@ -140,6 +127,13 @@ class ChildProcessLauncher::Context
#if defined(OS_LINUX)
// On Linux, we need to add some extra file descriptors for crash handling
// and the sandbox.
+ bool is_renderer =
+ cmd_line->GetSwitchValueASCII(switches::kProcessType) ==
+ switches::kRendererProcess;
+ bool is_plugin =
+ cmd_line->GetSwitchValueASCII(switches::kProcessType) ==
+ switches::kPluginProcess;
+
if (is_renderer || is_plugin) {
int crash_signal_fd;
if (is_renderer) {
@@ -190,7 +184,7 @@ class ChildProcessLauncher::Context
this,
&ChildProcessLauncher::Context::Notify,
#if defined(OS_LINUX)
- zygote,
+ use_zygote,
#endif
handle));
}
@@ -269,6 +263,7 @@ ChildProcessLauncher::ChildProcessLauncher(
#if defined(OS_WIN)
const FilePath& exposed_dir,
#elif defined(OS_POSIX)
+ bool use_zygote,
const base::environment_vector& environ,
int ipcfd,
#endif
@@ -279,6 +274,7 @@ ChildProcessLauncher::ChildProcessLauncher(
#if defined(OS_WIN)
exposed_dir,
#elif defined(OS_POSIX)
+ use_zygote,
environ,
ipcfd,
#endif
diff --git a/chrome/browser/child_process_launcher.h b/chrome/browser/child_process_launcher.h
index d37cb57..ce1c04d 100644
--- a/chrome/browser/child_process_launcher.h
+++ b/chrome/browser/child_process_launcher.h
@@ -32,6 +32,7 @@ class ChildProcessLauncher {
#if defined(OS_WIN)
const FilePath& exposed_dir,
#elif defined(OS_POSIX)
+ bool use_zygote,
const base::environment_vector& environ,
int ipcfd,
#endif
diff --git a/chrome/browser/gpu_process_host.cc b/chrome/browser/gpu_process_host.cc
index c56be79..e35cdd9 100644
--- a/chrome/browser/gpu_process_host.cc
+++ b/chrome/browser/gpu_process_host.cc
@@ -17,7 +17,11 @@
#include "ipc/ipc_switches.h"
GpuProcessHost::GpuProcessHost() : last_routing_id_(1) {
- FilePath exe_path = ChildProcessHost::GetChildPath();
+ const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
+ std::wstring gpu_launcher =
+ browser_command_line.GetSwitchValue(switches::kGpuLauncher);
+
+ FilePath exe_path = ChildProcessHost::GetChildPath(gpu_launcher.empty());
if (exe_path.empty())
return;
@@ -35,11 +39,16 @@ GpuProcessHost::GpuProcessHost() : last_routing_id_(1) {
cmd_line->AppendSwitchWithValue(switches::kProcessChannelID,
ASCIIToWide(channel_id));
+ // If specified, prepend a launcher program to the command line.
+ if (!gpu_launcher.empty())
+ cmd_line->PrependWrapper(gpu_launcher);
+
// Spawn the child process asynchronously to avoid blocking the UI thread.
child_process_.reset(new ChildProcessLauncher(
#if defined(OS_WIN)
FilePath(),
#elif defined(POSIX)
+ false, // Never use the zygote (GPU plugin can't be sandboxed).
base::environment_vector(),
channel_->GetClientFileDescriptor(),
#endif
@@ -62,7 +71,7 @@ int32 GpuProcessHost::GetNextRoutingId() {
return ++last_routing_id_;
}
-int32 GpuProcessHost::NewRenderWidgetHostView(gfx::NativeViewId parent) {
+int32 GpuProcessHost::NewRenderWidgetHostView(GpuNativeWindowHandle parent) {
int32 routing_id = GetNextRoutingId();
Send(new GpuMsg_NewRenderWidgetHostView(parent, routing_id));
return routing_id;
diff --git a/chrome/browser/gpu_process_host.h b/chrome/browser/gpu_process_host.h
index 1856182..d107b88 100644
--- a/chrome/browser/gpu_process_host.h
+++ b/chrome/browser/gpu_process_host.h
@@ -7,11 +7,11 @@
#include <queue>
-#include "app/gfx/native_widget_types.h"
#include "base/basictypes.h"
#include "base/scoped_ptr.h"
#include "base/singleton.h"
#include "chrome/browser/child_process_launcher.h"
+#include "chrome/common/gpu_native_window_handle.h"
#include "chrome/common/message_router.h"
#include "ipc/ipc_channel_proxy.h"
@@ -28,7 +28,7 @@ class GpuProcessHost : public IPC::Channel::Sender,
// Creates the new remote view and returns the routing ID for the view, or 0
// on failure.
- int32 NewRenderWidgetHostView(gfx::NativeViewId parent);
+ int32 NewRenderWidgetHostView(GpuNativeWindowHandle parent);
// IPC::Channel::Sender implementation.
virtual bool Send(IPC::Message* msg);
diff --git a/chrome/browser/nacl_process_host.cc b/chrome/browser/nacl_process_host.cc
index e84d76c..da40335 100644
--- a/chrome/browser/nacl_process_host.cc
+++ b/chrome/browser/nacl_process_host.cc
@@ -72,7 +72,7 @@ bool NaClProcessHost::LaunchSelLdr() {
return false;
// Build command line for nacl.
- FilePath exe_path = GetChildPath();
+ FilePath exe_path = GetChildPath(true);
if (exe_path.empty())
return false;
@@ -115,6 +115,7 @@ bool NaClProcessHost::LaunchSelLdr() {
#if defined(OS_WIN)
FilePath(),
#elif defined(OS_POSIX)
+ false,
base::environment_vector(),
#endif
cmd_line);
diff --git a/chrome/browser/plugin_process_host.cc b/chrome/browser/plugin_process_host.cc
index afc2486..ea47444 100644
--- a/chrome/browser/plugin_process_host.cc
+++ b/chrome/browser/plugin_process_host.cc
@@ -336,9 +336,12 @@ bool PluginProcessHost::Init(const WebPluginInfo& info,
if (!CreateChannel())
return false;
- // Build command line for plugin, we have to quote the plugin's path to deal
- // with spaces.
- FilePath exe_path = GetChildPath();
+ // Build command line for plugin. When we have a plugin launcher, we can't
+ // allow "self" on linux and we need the real file path.
+ const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
+ std::wstring plugin_launcher =
+ browser_command_line.GetSwitchValue(switches::kPluginLauncher);
+ FilePath exe_path = GetChildPath(plugin_launcher.empty());
if (exe_path.empty())
return false;
@@ -379,8 +382,6 @@ bool PluginProcessHost::Init(const WebPluginInfo& info,
#endif
};
- const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
-
for (size_t i = 0; i < arraysize(switch_names); ++i) {
if (browser_command_line.HasSwitch(switch_names[i])) {
cmd_line->AppendSwitchWithValue(
@@ -390,8 +391,6 @@ bool PluginProcessHost::Init(const WebPluginInfo& info,
}
// If specified, prepend a launcher program to the command line.
- std::wstring plugin_launcher =
- browser_command_line.GetSwitchValue(switches::kPluginLauncher);
if (!plugin_launcher.empty())
cmd_line->PrependWrapper(plugin_launcher);
@@ -434,6 +433,7 @@ bool PluginProcessHost::Init(const WebPluginInfo& info,
#if defined(OS_WIN)
FilePath(),
#elif defined(OS_POSIX)
+ false,
env,
#endif
cmd_line);
diff --git a/chrome/browser/renderer_host/backing_store_glx.h b/chrome/browser/renderer_host/backing_store_glx.h
deleted file mode 100644
index 534c052..0000000
--- a/chrome/browser/renderer_host/backing_store_glx.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 2010 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.
-
-#ifndef CHROME_BROWSER_RENDERER_HOST_BACKING_STORE_GLX_H_
-#define CHROME_BROWSER_RENDERER_HOST_BACKING_STORE_GLX_H_
-
-#include "base/basictypes.h"
-#include "build/build_config.h"
-#include "chrome/browser/renderer_host/backing_store.h"
-#include "chrome/common/x11_util.h"
-
-class BackingStoreGLX : public BackingStore {
- public:
- // Create a backing store on the X server. The visual is an Xlib Visual
- // describing the format of the target window and the depth is the color
- // depth of the X window which will be drawn into.
- BackingStoreGLX(RenderWidgetHost* widget,
- const gfx::Size& size,
- void* visual,
- int depth);
-
- // This is for unittesting only. An object constructed using this constructor
- // will silently ignore all paints
- BackingStoreGLX(RenderWidgetHost* widget, const gfx::Size& size);
-
- virtual ~BackingStoreGLX();
-
- Display* display() const { return display_; }
- XID root_window() const { return root_window_; }
-
- // Copy from the server-side backing store to the target window
- // display: the display of the backing store and target window
- // damage: the area to copy
- // target: the X id of the target window
- void ShowRect(const gfx::Rect& damage, XID target);
-
- // Paints the server-side backing store data to a SkBitmap. On failure, the
- // return bitmap will be isNull().
- SkBitmap PaintRectToBitmap(const gfx::Rect& rect);
-
-#if defined(TOOLKIT_GTK)
- // Paint the backing store into the target's |dest_rect|.
- void PaintToRect(const gfx::Rect& dest_rect, GdkDrawable* target);
-#endif
-
- // BackingStore implementation.
- virtual size_t MemorySize();
- virtual void PaintRect(base::ProcessHandle process,
- TransportDIB* bitmap,
- const gfx::Rect& bitmap_rect,
- const gfx::Rect& copy_rect);
- virtual void ScrollRect(int dx, int dy,
- const gfx::Rect& clip_rect,
- const gfx::Size& view_size);
-
- private:
- Display* const display_;
-
- // The parent window for this backing store.
- const XID root_window_;
-
- unsigned int texture_id_; // 0 when uninitialized.
-
- // The size of the texture loaded into GL. This is 0x0 when there is no
- // texture loaded. This may be different than the size of the backing store
- // because we could have been resized without yet getting the updated
- // bitmap.
- gfx::Size texture_size_;
-
- DISALLOW_COPY_AND_ASSIGN(BackingStoreGLX);
-};
-
-#endif // CHROME_BROWSER_RENDERER_HOST_BACKING_STORE_GLX_H_
diff --git a/chrome/browser/renderer_host/backing_store_manager_glx.cc b/chrome/browser/renderer_host/backing_store_manager_glx.cc
deleted file mode 100644
index d220bb2..0000000
--- a/chrome/browser/renderer_host/backing_store_manager_glx.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2009 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 "chrome/browser/renderer_host/backing_store_manager_glx.h"
-
-#include <GL/gl.h>
-#include <X11/Xutil.h>
-
-#include "base/scoped_ptr.h"
-#include "chrome/common/x11_util.h"
-
-namespace {
-
-// scoped_ptr functor for XFree().
-class ScopedPtrXFree {
- public:
- inline void operator()(void* x) const {
- ::XFree(x);
- }
-};
-
-} // namespace
-
-BackingStoreManagerGlx::BackingStoreManagerGlx()
- : display_(x11_util::GetXDisplay()),
- tried_to_init_(false),
- context_(NULL),
- previous_window_id_(0) {
-}
-
-BackingStoreManagerGlx::~BackingStoreManagerGlx() {
- if (context_)
- glXDestroyContext(display_, context_);
-}
-
-GLXContext BackingStoreManagerGlx::BindContext(XID window_id) {
- if (tried_to_init_) {
- if (!context_)
- return NULL;
- if (!previous_window_id_ || previous_window_id_ != window_id)
- ::glXMakeCurrent(display_, window_id, context_);
- previous_window_id_ = window_id;
- return context_;
- }
- tried_to_init_ = true;
-
- int attrib_list[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None };
- scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> visual_info(
- ::glXChooseVisual(display_, 0, attrib_list));
- if (!visual_info.get())
- return NULL;
-
- context_ = ::glXCreateContext(display_, visual_info.get(), NULL, True);
- ::glXMakeCurrent(display_, window_id, context_);
- return context_;
-}
diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc
index 3ca726c..b4e57df 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.cc
+++ b/chrome/browser/renderer_host/browser_render_process_host.cc
@@ -271,9 +271,19 @@ bool BrowserRenderProcessHost::Init(bool is_extensions_process,
widget_helper_,
request_context);
+ std::wstring renderer_prefix;
+#if defined(OS_POSIX)
+ // A command prefix is something prepended to the command line of the spawned
+ // process. It is supported only on POSIX systems.
+ const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
+ renderer_prefix =
+ browser_command_line.GetSwitchValue(switches::kRendererCmdPrefix);
+#endif // defined(OS_POSIX)
+
// Find the renderer before creating the channel so if this fails early we
// return without creating the channel.
- FilePath renderer_path = ChildProcessHost::GetChildPath();
+ FilePath renderer_path = ChildProcessHost::GetChildPath(
+ renderer_prefix.empty());
if (renderer_path.empty())
return false;
@@ -315,15 +325,20 @@ bool BrowserRenderProcessHost::Init(bool is_extensions_process,
// Build command line for renderer. We call AppendRendererCommandLine()
// first so the process type argument will appear first.
CommandLine* cmd_line = new CommandLine(renderer_path);
+ if (!renderer_prefix.empty())
+ cmd_line->PrependWrapper(renderer_prefix);
AppendRendererCommandLine(cmd_line);
cmd_line->AppendSwitchWithValue(switches::kProcessChannelID,
ASCIIToWide(channel_id));
// Spawn the child process asynchronously to avoid blocking the UI thread.
+ // As long as there's no renderer prefix, we can use the zygote process
+ // at this stage.
child_process_.reset(new ChildProcessLauncher(
#if defined(OS_WIN)
FilePath(),
#elif defined(POSIX)
+ renderer_prefix.empty(),
base::environment_vector(),
channel_->GetClientFileDescriptor(),
#endif
@@ -453,17 +468,6 @@ void BrowserRenderProcessHost::AppendRendererCommandLine(
field_trial_states);
}
- // A command prefix is something prepended to the command line of the spawned
- // process. It is supported only on POSIX systems.
-#if defined(OS_POSIX)
- if (browser_command_line.HasSwitch(switches::kRendererCmdPrefix)) {
- // launch the renderer child with some prefix (usually "gdb --args")
- const std::wstring prefix =
- browser_command_line.GetSwitchValue(switches::kRendererCmdPrefix);
- command_line->PrependWrapper(prefix);
- }
-#endif // defined(OS_POSIX)
-
ChildProcessHost::SetCrashReporterCommandLine(command_line);
const std::string user_data_dir =
diff --git a/chrome/browser/renderer_host/gpu_view_host.cc b/chrome/browser/renderer_host/gpu_view_host.cc
index 5addbc0..9b9404a 100644
--- a/chrome/browser/renderer_host/gpu_view_host.cc
+++ b/chrome/browser/renderer_host/gpu_view_host.cc
@@ -8,7 +8,7 @@
#include "chrome/browser/renderer_host/backing_store_proxy.h"
#include "chrome/common/gpu_messages.h"
-GpuViewHost::GpuViewHost(RenderWidgetHost* widget, gfx::NativeView parent)
+GpuViewHost::GpuViewHost(RenderWidgetHost* widget, GpuNativeWindowHandle parent)
: widget_(widget),
process_(GpuProcessHost::Get()),
routing_id_(0) {
@@ -16,8 +16,7 @@ GpuViewHost::GpuViewHost(RenderWidgetHost* widget, gfx::NativeView parent)
// TODO(brettw) handle error.
return;
}
- routing_id_ = process_->NewRenderWidgetHostView(
- gfx::IdFromNativeView(parent));
+ routing_id_ = process_->NewRenderWidgetHostView(parent);
}
GpuViewHost::~GpuViewHost() {
diff --git a/chrome/browser/renderer_host/gpu_view_host.h b/chrome/browser/renderer_host/gpu_view_host.h
index 11f417a..adafbf7 100644
--- a/chrome/browser/renderer_host/gpu_view_host.h
+++ b/chrome/browser/renderer_host/gpu_view_host.h
@@ -5,8 +5,8 @@
#ifndef CHROME_BROWSER_RENDERER_HOST_GPU_VIEW_HOST_H_
#define CHROME_BROWSER_RENDERER_HOST_GPU_VIEW_HOST_H_
-#include "app/gfx/native_widget_types.h"
#include "base/basictypes.h"
+#include "chrome/common/gpu_native_window_handle.h"
class BackingStore;
class GpuProcessHost;
@@ -19,7 +19,7 @@ class Size;
// A proxy for the GPU process' window for rendering pages.
class GpuViewHost {
public:
- GpuViewHost(RenderWidgetHost* widget, gfx::NativeView parent);
+ GpuViewHost(RenderWidgetHost* widget, GpuNativeWindowHandle parent);
~GpuViewHost();
// Creates a new backing store in the GPU process and returns ownership of
diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
index d7a7ff2..ced2f16 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
@@ -39,6 +39,10 @@
static const int kMaxWindowWidth = 4000;
static const int kMaxWindowHeight = 4000;
+// True if we're doing out-of-process painting via the GPU process.
+// TODO(brettw) make this a command line option.
+static const bool kUseGPURendering = false;
+
using WebKit::WebInputEventFactory;
// This class is a simple convenience wrapper for Gtk functions. It has only
@@ -334,9 +338,6 @@ void RenderWidgetHostViewGtk::InitAsChild() {
key_bindings_handler_.reset(new GtkKeyBindingsHandler(view_.get()));
plugin_container_manager_.set_host_widget(view_.get());
gtk_widget_show(view_.get());
-
- // Uncomment this line to use out-of-process painting.
- // gpu_view_host_.reset(new GpuViewHost(host_, GetNativeView()));
}
void RenderWidgetHostViewGtk::InitAsPopup(
@@ -608,8 +609,19 @@ void RenderWidgetHostViewGtk::AppendInputMethodsContextMenu(MenuGtk* menu) {
BackingStore* RenderWidgetHostViewGtk::AllocBackingStore(
const gfx::Size& size) {
- if (gpu_view_host_.get())
+ if (kUseGPURendering) {
+ // Use a special GPU accelerated backing store.
+ if (!gpu_view_host_.get()) {
+ // Here we lazily make the GpuViewHost. This must be allocated when we
+ // have a native view realized, which happens sometime after creation
+ // when our owner puts us in the parent window.
+ DCHECK(GetNativeView());
+ XID window_xid = x11_util::GetX11WindowFromGtkWidget(GetNativeView());
+ gpu_view_host_.reset(new GpuViewHost(host_, window_xid));
+ }
return gpu_view_host_->CreateBackingStore(size);
+ }
+
return new BackingStoreX(host_, size,
x11_util::GetVisualFromGtkWidget(view_.get()),
gtk_widget_get_visual(view_.get())->depth);
@@ -621,17 +633,13 @@ void RenderWidgetHostViewGtk::SetBackground(const SkBitmap& background) {
}
void RenderWidgetHostViewGtk::Paint(const gfx::Rect& damage_rect) {
- GdkWindow* window = view_.get()->window;
-
- if (gpu_view_host_.get()) {
+ if (kUseGPURendering) {
// When we're proxying painting, we don't actually display the web page
- // ourselves. We clear it white in case the proxy window isn't visible
- // yet we won't show gibberish.
- if (window)
- gdk_window_clear(window);
+ // ourselves.
return;
}
+ GdkWindow* window = view_.get()->window;
DCHECK(!about_to_validate_and_paint_);
invalid_rect_ = damage_rect;
diff --git a/chrome/browser/utility_process_host.cc b/chrome/browser/utility_process_host.cc
index 29ed98f..3d3c317 100644
--- a/chrome/browser/utility_process_host.cc
+++ b/chrome/browser/utility_process_host.cc
@@ -52,7 +52,7 @@ bool UtilityProcessHost::StartUpdateManifestParse(const std::string& xml) {
}
FilePath UtilityProcessHost::GetUtilityProcessCmd() {
- return GetChildPath();
+ return GetChildPath(true);
}
bool UtilityProcessHost::StartProcess(const FilePath& exposed_dir) {
@@ -106,6 +106,7 @@ bool UtilityProcessHost::StartProcess(const FilePath& exposed_dir) {
#if defined(OS_WIN)
exposed_dir,
#elif defined(OS_POSIX)
+ false,
base::environment_vector(),
#endif
cmd_line);
diff --git a/chrome/browser/worker_host/worker_process_host.cc b/chrome/browser/worker_host/worker_process_host.cc
index 3373e2f..562daea 100644
--- a/chrome/browser/worker_host/worker_process_host.cc
+++ b/chrome/browser/worker_host/worker_process_host.cc
@@ -79,7 +79,7 @@ bool WorkerProcessHost::Init() {
if (!CreateChannel())
return false;
- FilePath exe_path = GetChildPath();
+ FilePath exe_path = GetChildPath(true);
if (exe_path.empty())
return false;
@@ -143,6 +143,7 @@ bool WorkerProcessHost::Init() {
#if defined(OS_WIN)
FilePath(),
#elif defined(OS_POSIX)
+ false,
base::environment_vector(),
#endif
cmd_line);
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 6cdf599..01a1f52 100755
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -585,30 +585,44 @@
'dependencies': [
'../base/base.gyp:base',
'common',
- ],
- 'conditions': [
- ['OS=="win"', {
- 'include_dirs': [
- 'third_party/wtl/include',
- ],
- 'sources': [
- 'gpu/gpu_backing_store.cc',
- 'gpu/gpu_backing_store.h',
- 'gpu/gpu_view_win.cc',
- 'gpu/gpu_view_win.h',
- ],
- }]
+ '../skia/skia.gyp:skia',
],
'sources': [
+ 'gpu/gpu_backing_store_win.cc',
+ 'gpu/gpu_backing_store_win.h',
'gpu/gpu_main.cc',
'gpu/gpu_process.cc',
'gpu/gpu_process.h',
'gpu/gpu_thread.cc',
'gpu/gpu_thread.h',
+ 'gpu/gpu_view_win.cc',
+ 'gpu/gpu_view_win.h',
],
'include_dirs': [
'..',
],
+ 'conditions': [
+ ['OS=="win"', {
+ 'include_dirs': [
+ 'third_party/wtl/include',
+ ],
+ }],
+ ['OS=="linux"', {
+ 'sources': [
+ 'gpu/gpu_backing_store_glx.cc',
+ 'gpu/gpu_backing_store_glx.h',
+ 'gpu/gpu_backing_store_glx_context.cc',
+ 'gpu/gpu_backing_store_glx_context.h',
+ 'gpu/gpu_view_x.cc',
+ 'gpu/gpu_view_x.h',
+ 'gpu/x_util.cc',
+ 'gpu/x_util.h',
+ ],
+ 'dependencies': [
+ '../gpu/gpu.gyp:gl_libs',
+ ],
+ }],
+ ],
},
{
'target_name': 'worker',
diff --git a/chrome/common/child_process_host.cc b/chrome/common/child_process_host.cc
index d7f6ce1..9fb6b52 100644
--- a/chrome/common/child_process_host.cc
+++ b/chrome/common/child_process_host.cc
@@ -83,7 +83,7 @@ ChildProcessHost::~ChildProcessHost() {
}
// static
-FilePath ChildProcessHost::GetChildPath() {
+FilePath ChildProcessHost::GetChildPath(bool allow_self) {
FilePath child_path;
child_path = CommandLine::ForCurrentProcess()->GetSwitchValuePath(
@@ -101,10 +101,8 @@ FilePath ChildProcessHost::GetChildPath() {
#if defined(OS_LINUX)
// Use /proc/self/exe rather than our known binary path so updates
// can't swap out the binary from underneath us.
- if (!CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kRendererCmdPrefix)) {
+ if (allow_self)
return FilePath("/proc/self/exe");
- }
#endif
// On most platforms, the child executable is the same as the current
@@ -134,6 +132,7 @@ void ChildProcessHost::Launch(
#if defined(OS_WIN)
const FilePath& exposed_dir,
#elif defined(OS_POSIX)
+ bool use_zygote,
const base::environment_vector& environ,
#endif
CommandLine* cmd_line) {
@@ -141,6 +140,7 @@ void ChildProcessHost::Launch(
#if defined(OS_WIN)
exposed_dir,
#elif defined(OS_POSIX)
+ use_zygote,
environ,
channel_->GetClientFileDescriptor(),
#endif
diff --git a/chrome/common/child_process_host.h b/chrome/common/child_process_host.h
index 1ca547b..ec6e86d 100644
--- a/chrome/common/child_process_host.h
+++ b/chrome/common/child_process_host.h
@@ -34,9 +34,18 @@ class ChildProcessHost : public ResourceDispatcherHost::Receiver,
// Returns the pathname to be used for a child process. If a subprocess
// pathname was specified on the command line, that will be used. Otherwise,
// the default child process pathname will be returned. On most platforms,
- // this will be the same as the currently-executing process. On failure,
- // returns an empty wstring.
- static FilePath GetChildPath();
+ // this will be the same as the currently-executing process.
+ //
+ // The argument allow_self is used on Linux to indicate that we allow us to
+ // fork from /proc/self/exe rather than using the "real" app path. This
+ // prevents autoupdate from confusing us if it changes the file out from
+ // under us. You will generally want to set this to true, except when there
+ // is an override to the command line (for example, we're forking a renderer
+ // in gdb). In this case, you'd use GetChildPath to get the real executable
+ // file name, and then prepend the GDB command to the command line.
+ //
+ // On failure, returns an empty FilePath.
+ static FilePath GetChildPath(bool allow_self);
// Prepares command_line for crash reporting as appropriate. On Linux and
// Mac, a command-line flag to enable crash reporting in the child process
@@ -79,6 +88,7 @@ class ChildProcessHost : public ResourceDispatcherHost::Receiver,
#if defined(OS_WIN)
const FilePath& exposed_dir,
#elif defined(OS_POSIX)
+ bool use_zygote,
const base::environment_vector& environ,
#endif
CommandLine* cmd_line);
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 251b382..633884a 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -298,6 +298,10 @@ const char kFirstRun[] = "first-run";
// current details.
const char kForceFieldTestNameAndValue[] = "force-fieldtest";
+// Extra command line options for launching the GPU process (normally used
+// for debugging). Use like renderer-cmd-prefix.
+const char kGpuLauncher[] = "gpu-launcher";
+
// Makes this process a GPU sub-process.
const char kGpuProcess[] = "gpu-process";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 15b1975..05917ba 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -96,6 +96,7 @@ extern const char kExtensionsUpdateFrequency[];
extern const char kFileDescriptorLimit[];
extern const char kFirstRun[];
extern const char kForceFieldTestNameAndValue[];
+extern const char kGpuLauncher[];
extern const char kGpuProcess[];
extern const char kHideIcons[];
extern const char kHomePage[];
diff --git a/chrome/common/gpu_messages.h b/chrome/common/gpu_messages.h
index 52e3d6f..fc2a826 100644
--- a/chrome/common/gpu_messages.h
+++ b/chrome/common/gpu_messages.h
@@ -9,9 +9,11 @@
#include "app/gfx/native_widget_types.h"
#include "base/basictypes.h"
+#include "base/process.h"
#include "base/gfx/rect.h"
#include "base/gfx/size.h"
#include "chrome/common/common_param_traits.h"
+#include "chrome/common/gpu_native_window_handle.h"
#include "chrome/common/transport_dib.h"
namespace IPC {
diff --git a/chrome/common/gpu_messages_internal.h b/chrome/common/gpu_messages_internal.h
index 73a82f1..4209a12 100644
--- a/chrome/common/gpu_messages_internal.h
+++ b/chrome/common/gpu_messages_internal.h
@@ -16,7 +16,7 @@
IPC_BEGIN_MESSAGES(Gpu)
IPC_MESSAGE_CONTROL2(GpuMsg_NewRenderWidgetHostView,
- gfx::NativeViewId, /* parent window */
+ GpuNativeWindowHandle, /* parent window */
int32 /* view_id */)
// Creates a new backing store.
diff --git a/chrome/common/gpu_native_window_handle.h b/chrome/common/gpu_native_window_handle.h
new file mode 100644
index 0000000..9390b77
--- /dev/null
+++ b/chrome/common/gpu_native_window_handle.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2010 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.
+
+#ifndef CHROME_COMMON_GPU_NATIVE_WINDOW_HANDLE_H_
+#define CHROME_COMMON_GPU_NATIVE_WINDOW_HANDLE_H_
+
+#include "build/build_config.h"
+
+// This file defines the window handle type used by the GPU process IPC layer.
+// This is different than gfx::NativeWindow[Id] since on X, this is an XID.
+// Normally, Chrome deals with either GTK window pointers, or magic window
+// IDs that the app generates. The GPU process needs to know the real XID.
+
+#if defined(OS_WIN)
+
+#include <windows.h>
+
+typedef HWND GpuNativeWindowHandle;
+
+#elif defined(OS_LINUX)
+
+// Forward declar XID ourselves to avoid pulling in all of the X headers, which
+// can cause compile problems for some parts of the project.
+typedef unsigned long XID;
+
+typedef XID GpuNativeWindowHandle;
+
+#elif defined(OS_MACOSX)
+
+// The GPU process isn't supported on Mac yet. Defining this arbitrarily allows
+// us to not worry about the integration points not compiling.
+typedef int GpuNativeWindowHandle;
+
+#else
+
+#error define GpuNativeWindowHandle
+
+#endif
+
+#endif // CHROME_COMMON_GPU_NATIVE_WINDOW_HANDLE_H_
diff --git a/chrome/browser/renderer_host/backing_store_gl.cc b/chrome/gpu/gpu_backing_store_glx.cc
index 414f071..e653284 100644
--- a/chrome/browser/renderer_host/backing_store_gl.cc
+++ b/chrome/gpu/gpu_backing_store_glx.cc
@@ -1,32 +1,32 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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 "chrome/browser/renderer_host/backing_store.h"
+#include "chrome/gpu/gpu_backing_store_glx.h"
-#include <GL/gl.h>
+#include <GL/glew.h>
#include "base/scoped_ptr.h"
-#include "chrome/browser/renderer_host/backing_store_manager.h"
-#include "chrome/browser/renderer_host/backing_store_manager_glx.h"
-#include "chrome/browser/renderer_host/render_widget_host.h"
-#include "chrome/browser/renderer_host/render_widget_host_view.h"
+#include "chrome/common/gpu_messages.h"
#include "chrome/common/transport_dib.h"
-#include "chrome/common/x11_util.h"
+#include "chrome/gpu/gpu_backing_store_glx_context.h"
+#include "chrome/gpu/gpu_thread.h"
+#include "chrome/gpu/gpu_view_x.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/skia/include/core/SkBitmap.h"
-BackingStore::BackingStore(RenderWidgetHost* widget,
- const gfx::Size& size,
- void* visual,
- int depth)
- : render_widget_host_(widget),
+GpuBackingStoreGLX::GpuBackingStoreGLX(GpuViewX* view,
+ GpuThread* gpu_thread,
+ int32 routing_id,
+ const gfx::Size& size)
+ : view_(view),
+ gpu_thread_(gpu_thread),
+ routing_id_(routing_id),
size_(size),
- display_(x11_util::GetXDisplay()),
- root_window_(x11_util::GetX11RootWindow()),
texture_id_(0) {
- XID id = x11_util::GetX11WindowFromGtkWidget(widget->view()->GetNativeView());
- BackingStoreManager::GetGlManager()->BindContext(id);
+ gpu_thread_->AddRoute(routing_id_, this);
+
+ view_->BindContext(); // Must do this before issuing OpenGl.
glGenTextures(1, &texture_id_);
glBindTexture(GL_TEXTURE_2D, texture_id_);
@@ -37,89 +37,59 @@ BackingStore::BackingStore(RenderWidgetHost* widget,
DCHECK(glGetError() == GL_NO_ERROR);
}
-BackingStore::BackingStore(RenderWidgetHost* widget, const gfx::Size& size)
- : render_widget_host_(widget),
- size_(size),
- display_(NULL),
- root_window_(0),
- texture_id_(0) {
-}
-
-BackingStore::~BackingStore() {
+GpuBackingStoreGLX::~GpuBackingStoreGLX() {
if (texture_id_)
glDeleteTextures(1, &texture_id_);
+ gpu_thread_->RemoveRoute(routing_id_);
}
-void BackingStore::ShowRect(const gfx::Rect& damage, XID target) {
- DCHECK(texture_id_ > 0);
-
- // TODO(brettw) is this necessray?
- XID id = x11_util::GetX11WindowFromGtkWidget(
- render_widget_host_->view()->GetNativeView());
- BackingStoreManager::GetGlManager()->BindContext(id);
-
- glViewport(0, 0, size_.width(), size_.height());
-
- // TODO(brettw) only repaint the damaged area. This currently erases and
- // repaints the entire screen.
-
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, texture_id_);
-
- // TODO(brettw) use vertex buffers.
- // TODO(brettw) make this so we use the texture size rather than the whole
- // area size so we don't stretch bitmaps.
- glBegin(GL_QUADS);
- glTexCoord2f(0.0f, 0.0f);
- glVertex2f(-1.0, 1.0);
-
- glTexCoord2f(0.0f, 1.0f);
- glVertex2f(-1.0, -1.0);
-
- glTexCoord2f(1.0f, 1.0f);
- glVertex2f(1.0, -1.0);
-
- glTexCoord2f(1.0f, 0.0f);
- glVertex2f(1.0, 1.0);
- glEnd();
- DCHECK(glGetError() == GL_NO_ERROR);
-
- // TODO(brettw) when we no longer stretch non-fitting bitmaps, we should
- // paint white over any unpainted area here.
-
- glXSwapBuffers(display_, id);
+void GpuBackingStoreGLX::OnMessageReceived(const IPC::Message& msg) {
+ IPC_BEGIN_MESSAGE_MAP(GpuBackingStoreGLX, msg)
+ IPC_MESSAGE_HANDLER(GpuMsg_PaintToBackingStore, OnPaintToBackingStore)
+ IPC_MESSAGE_HANDLER(GpuMsg_ScrollBackingStore, OnScrollBackingStore)
+ IPC_END_MESSAGE_MAP_EX()
}
-SkBitmap BackingStore::PaintRectToBitmap(const gfx::Rect& rect) {
- NOTIMPLEMENTED();
- return SkBitmap();
+void GpuBackingStoreGLX::OnChannelConnected(int32 peer_pid) {
}
-#if defined(TOOLKIT_GTK)
-void BackingStore::PaintToRect(const gfx::Rect& rect, GdkDrawable* target) {
+void GpuBackingStoreGLX::OnChannelError() {
+ // FIXME(brettw) does this mean we aren't getting any more messages and we
+ // should delete outselves?
NOTIMPLEMENTED();
}
-#endif
-
-// Paint the given transport DIB into our backing store.
-void BackingStore::PaintRect(base::ProcessHandle process,
- TransportDIB* bitmap,
- const gfx::Rect& bitmap_rect,
- const gfx::Rect& copy_rect) {
- if (!display_)
- return;
- if (bitmap_rect.IsEmpty() || copy_rect.IsEmpty())
- return;
+void GpuBackingStoreGLX::OnPaintToBackingStore(
+ base::ProcessId source_process_id,
+ TransportDIB::Id id,
+ const gfx::Rect& bitmap_rect,
+ const std::vector<gfx::Rect>& copy_rects) {
+ TransportDIB* dib = TransportDIB::Map(id);
+ view_->BindContext();
scoped_ptr<skia::PlatformCanvas> canvas(
- bitmap->GetPlatformCanvas(bitmap_rect.width(), bitmap_rect.height()));
+ dib->GetPlatformCanvas(bitmap_rect.width(), bitmap_rect.height()));
const SkBitmap& transport_bitmap =
canvas->getTopPlatformDevice().accessBitmap(false);
+ for (size_t i = 0; i < copy_rects.size(); i++)
+ PaintOneRectToBackingStore(transport_bitmap, bitmap_rect, copy_rects[i]);
+
+ gpu_thread_->Send(new GpuHostMsg_PaintToBackingStore_ACK(routing_id_));
+
+ view_->Repaint();
+}
+
+void GpuBackingStoreGLX::OnScrollBackingStore(int dx, int dy,
+ const gfx::Rect& clip_rect,
+ const gfx::Size& view_size) {
+
+}
+
+void GpuBackingStoreGLX::PaintOneRectToBackingStore(
+ const SkBitmap& transport_bitmap,
+ const gfx::Rect& bitmap_rect,
+ const gfx::Rect& copy_rect) {
// Make a bitmap referring to the correct subset of the input bitmap.
SkBitmap copy_bitmap;
if (copy_rect.x() == 0 &&
@@ -195,16 +165,3 @@ void BackingStore::PaintRect(base::ProcessHandle process,
*/
}
}
-
-void BackingStore::ScrollRect(base::ProcessHandle process,
- TransportDIB* bitmap,
- const gfx::Rect& bitmap_rect,
- int dx, int dy,
- const gfx::Rect& clip_rect,
- const gfx::Size& view_size) {
- NOTIMPLEMENTED();
-}
-
-size_t BackingStore::MemorySize() {
- return texture_size_.GetArea() * 4;
-}
diff --git a/chrome/gpu/gpu_backing_store_glx.h b/chrome/gpu/gpu_backing_store_glx.h
new file mode 100644
index 0000000..b0c1d65
--- /dev/null
+++ b/chrome/gpu/gpu_backing_store_glx.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2010 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.
+
+#ifndef CHROME_GPU_GPU_BACKING_STORE_GLX_H_
+#define CHROME_GPU_GPU_BACKING_STORE_GLX_H_
+
+#include "base/basictypes.h"
+#include "base/process.h"
+#include "chrome/common/transport_dib.h"
+#include "chrome/common/x11_util.h"
+#include "ipc/ipc_channel.h"
+
+class GpuViewX;
+class GpuThread;
+class SkBitmap;
+
+class GpuBackingStoreGLX : public IPC::Channel::Listener {
+ public:
+ GpuBackingStoreGLX(GpuViewX* view,
+ GpuThread* gpu_thread,
+ int32 routing_id,
+ const gfx::Size& size);
+ ~GpuBackingStoreGLX();
+
+ const gfx::Size& size() const { return size_; }
+ const gfx::Size& texture_size() const { return texture_size_; }
+ unsigned int texture_id() const { return texture_id_; }
+
+ // IPC::Channel::Listener implementation.
+ virtual void OnMessageReceived(const IPC::Message& message);
+ virtual void OnChannelConnected(int32 peer_pid);
+ virtual void OnChannelError();
+
+ private:
+ // Message handlers.
+ void OnPaintToBackingStore(base::ProcessId source_process_id,
+ TransportDIB::Id id,
+ const gfx::Rect& bitmap_rect,
+ const std::vector<gfx::Rect>& copy_rects);
+ void OnScrollBackingStore(int dx, int dy,
+ const gfx::Rect& clip_rect,
+ const gfx::Size& view_size);
+
+ void PaintOneRectToBackingStore(const SkBitmap& transport_bitmap,
+ const gfx::Rect& bitmap_rect,
+ const gfx::Rect& copy_rect);
+
+ GpuViewX* view_;
+ GpuThread* gpu_thread_;
+ int32 routing_id_;
+ gfx::Size size_;
+
+ unsigned int texture_id_; // 0 when uninitialized.
+
+ // The size of the texture loaded into GL. This is 0x0 when there is no
+ // texture loaded. This may be different than the size of the backing store
+ // because we could have been resized without yet getting the updated
+ // bitmap.
+ gfx::Size texture_size_;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuBackingStoreGLX);
+};
+
+#endif // CHROME_GPU_GPU_BACKING_STORE_GLX_H_
diff --git a/chrome/gpu/gpu_backing_store_glx_context.cc b/chrome/gpu/gpu_backing_store_glx_context.cc
new file mode 100644
index 0000000..e66f07b
--- /dev/null
+++ b/chrome/gpu/gpu_backing_store_glx_context.cc
@@ -0,0 +1,54 @@
+// Copyright (c) 2010 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 "chrome/gpu/gpu_backing_store_glx_context.h"
+
+#include "base/scoped_ptr.h"
+#include "chrome/common/x11_util.h"
+#include "chrome/gpu/gpu_thread.h"
+
+// Must be last.
+#include <GL/glew.h>
+#include <GL/glxew.h>
+#include <X11/Xutil.h>
+
+GpuBackingStoreGLXContext::GpuBackingStoreGLXContext(GpuThread* gpu_thread)
+ : gpu_thread_(gpu_thread),
+ tried_to_init_(false),
+ context_(NULL),
+ previous_window_id_(0) {
+}
+
+GpuBackingStoreGLXContext::~GpuBackingStoreGLXContext() {
+ if (context_)
+ glXDestroyContext(gpu_thread_->display(), context_);
+}
+
+GLXContext GpuBackingStoreGLXContext::BindContext(XID window_id) {
+ if (tried_to_init_) {
+ if (!context_)
+ return NULL;
+ if (!previous_window_id_ || previous_window_id_ != window_id) {
+ bool success = ::glXMakeCurrent(gpu_thread_->display(), window_id,
+ context_);
+ DCHECK(success);
+ }
+ previous_window_id_ = window_id;
+ return context_;
+ }
+ tried_to_init_ = true;
+
+ int attrib_list[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None };
+ scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> visual_info(
+ ::glXChooseVisual(gpu_thread_->display(), 0, attrib_list));
+ if (!visual_info.get())
+ return NULL;
+
+ context_ = ::glXCreateContext(gpu_thread_->display(), visual_info.get(),
+ NULL, True);
+ bool success = ::glXMakeCurrent(gpu_thread_->display(), window_id, context_);
+ DCHECK(success);
+ glewInit();
+ return context_;
+}
diff --git a/chrome/browser/renderer_host/backing_store_manager_glx.h b/chrome/gpu/gpu_backing_store_glx_context.h
index cf6bbe2..211b010 100644
--- a/chrome/browser/renderer_host/backing_store_manager_glx.h
+++ b/chrome/gpu/gpu_backing_store_glx_context.h
@@ -1,21 +1,19 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
-#ifndef CHROME_BROWSER_RENDERER_HOST_BACKING_STORE_MANAGER_GLX_H_
-#define CHROME_BROWSER_RENDERER_HOST_BACKING_STORE_MANAGER_GLX_H_
-
-#include <GL/glx.h>
-#include <X11/Xlib.h>
+#ifndef CHROME_GPU_GPU_BACKING_STORE_GLX_CONTEXT_H_
+#define CHROME_GPU_GPU_BACKING_STORE_GLX_CONTEXT_H_
#include "base/basictypes.h"
+#include "chrome/gpu/x_util.h"
-class BackingStoreManagerGlx {
- public:
- BackingStoreManagerGlx();
- ~BackingStoreManagerGlx();
+class GpuThread;
- Display* display() const { return display_; }
+class GpuBackingStoreGLXContext {
+ public:
+ GpuBackingStoreGLXContext(GpuThread* gpu_thread);
+ ~GpuBackingStoreGLXContext();
// Returns the context, creating it if necessary, and binding it to the given
// display and window identified by the XID. This will avoid duplicate calls
@@ -24,7 +22,7 @@ class BackingStoreManagerGlx {
GLXContext BindContext(XID window_id);
private:
- Display* display_;
+ GpuThread* gpu_thread_;
// Set to true when we've tried to create the context. This prevents us from
// trying to initialize the OpenGL context over and over in the failure case.
@@ -37,7 +35,7 @@ class BackingStoreManagerGlx {
// duplicate "MakeCurrent" calls which are expensive.
XID previous_window_id_;
- DISALLOW_COPY_AND_ASSIGN(BackingStoreManagerGlx);
+ DISALLOW_COPY_AND_ASSIGN(GpuBackingStoreGLXContext);
};
-#endif // CHROME_BROWSER_RENDERER_HOST_BACKING_STORE_MANAGER_GLX_H_
+#endif // CHROME_GPU_GPU_BACKING_STORE_GLX_CONTEXT_H_
diff --git a/chrome/gpu/gpu_backing_store.cc b/chrome/gpu/gpu_backing_store_win.cc
index a5fafe2..1b4dcd5 100644
--- a/chrome/gpu/gpu_backing_store.cc
+++ b/chrome/gpu/gpu_backing_store_win.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/gpu/gpu_backing_store.h"
+#include "chrome/gpu/gpu_backing_store_win.h"
#include "app/gfx/gdi_util.h"
#include "app/win_util.h"
@@ -65,10 +65,10 @@ void CallStretchDIBits(HDC hdc, int dest_x, int dest_y, int dest_w, int dest_h,
} // namespace
-GpuBackingStore::GpuBackingStore(GpuViewWin* view,
- GpuThread* gpu_thread,
- int32 routing_id,
- const gfx::Size& size)
+GpuBackingStoreWin::GpuBackingStoreWin(GpuViewWin* view,
+ GpuThread* gpu_thread,
+ int32 routing_id,
+ const gfx::Size& size)
: view_(view),
gpu_thread_(gpu_thread),
routing_id_(routing_id),
@@ -86,7 +86,7 @@ GpuBackingStore::GpuBackingStore(GpuViewWin* view,
ReleaseDC(NULL, screen_dc);
}
-GpuBackingStore::~GpuBackingStore() {
+GpuBackingStoreWin::~GpuBackingStoreWin() {
gpu_thread_->RemoveRoute(routing_id_);
DCHECK(hdc_);
@@ -100,22 +100,22 @@ GpuBackingStore::~GpuBackingStore() {
DeleteDC(hdc_);
}
-void GpuBackingStore::OnMessageReceived(const IPC::Message& msg) {
- IPC_BEGIN_MESSAGE_MAP(GpuBackingStore, msg)
+void GpuBackingStoreWin::OnMessageReceived(const IPC::Message& msg) {
+ IPC_BEGIN_MESSAGE_MAP(GpuBackingStoreWin, msg)
IPC_MESSAGE_HANDLER(GpuMsg_PaintToBackingStore, OnPaintToBackingStore)
IPC_MESSAGE_HANDLER(GpuMsg_ScrollBackingStore, OnScrollBackingStore)
IPC_END_MESSAGE_MAP_EX()
}
-void GpuBackingStore::OnChannelConnected(int32 peer_pid) {
+void GpuBackingStoreWin::OnChannelConnected(int32 peer_pid) {
}
-void GpuBackingStore::OnChannelError() {
+void GpuBackingStoreWin::OnChannelError() {
// FIXME(brettw) does this mean we aren't getting any more messages and we
// should delete outselves?
}
-void GpuBackingStore::OnPaintToBackingStore(
+void GpuBackingStoreWin::OnPaintToBackingStore(
base::ProcessId source_process_id,
TransportDIB::Id id,
const gfx::Rect& bitmap_rect,
@@ -172,9 +172,9 @@ void GpuBackingStore::OnPaintToBackingStore(
gpu_thread_->Send(new GpuHostMsg_PaintToBackingStore_ACK(routing_id_));
}
-void GpuBackingStore::OnScrollBackingStore(int dx, int dy,
- const gfx::Rect& clip_rect,
- const gfx::Size& view_size) {
+void GpuBackingStoreWin::OnScrollBackingStore(int dx, int dy,
+ const gfx::Rect& clip_rect,
+ const gfx::Size& view_size) {
RECT damaged_rect, r = clip_rect.ToRECT();
ScrollDC(hdc_, dx, dy, NULL, &r, NULL, &damaged_rect);
diff --git a/chrome/gpu/gpu_backing_store.h b/chrome/gpu/gpu_backing_store_win.h
index bfe9941..ba7cf0c 100644
--- a/chrome/gpu/gpu_backing_store.h
+++ b/chrome/gpu/gpu_backing_store_win.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CHROME_GPU_GPU_BACKING_STORE_H_
-#define CHROME_GPU_GPU_BACKING_STORE_H_
+#ifndef CHROME_GPU_GPU_BACKING_STORE_WIN_H_
+#define CHROME_GPU_GPU_BACKING_STORE_WIN_H_
#include <windows.h>
@@ -23,13 +23,13 @@ class Rect;
class Size;
}
-class GpuBackingStore : public IPC::Channel::Listener {
+class GpuBackingStoreWin : public IPC::Channel::Listener {
public:
- GpuBackingStore(GpuViewWin* view,
- GpuThread* gpu_thread,
- int32 routing_id,
- const gfx::Size& size);
- ~GpuBackingStore();
+ GpuBackingStoreWin(GpuViewWin* view,
+ GpuThread* gpu_thread,
+ int32 routing_id,
+ const gfx::Size& size);
+ ~GpuBackingStoreWin();
gfx::Size size() const { return size_; }
HDC hdc() const { return hdc_; }
@@ -68,7 +68,7 @@ class GpuBackingStore : public IPC::Channel::Listener {
// Number of bits per pixel of the screen.
int color_depth_;
- DISALLOW_COPY_AND_ASSIGN(GpuBackingStore);
+ DISALLOW_COPY_AND_ASSIGN(GpuBackingStoreWin);
};
-#endif // CHROME_GPU_GPU_BACKING_STORE_H_
+#endif // CHROME_GPU_GPU_BACKING_STORE_WIN_H_
diff --git a/chrome/gpu/gpu_main.cc b/chrome/gpu/gpu_main.cc
index f4641ac..8dd5cc4 100644
--- a/chrome/gpu/gpu_main.cc
+++ b/chrome/gpu/gpu_main.cc
@@ -15,6 +15,9 @@
#if defined(OS_WIN)
#include "app/win_util.h"
+#elif defined(OS_LINUX)
+#include <dlfcn.h>
+#include <GL/glxew.h>
#endif
// Main function for starting the Gpu process.
@@ -30,6 +33,9 @@ int GpuMain(const MainFunctionParams& parameters) {
#if defined(OS_WIN)
win_util::ScopedCOMInitializer com_initializer;
+#elif defined(OS_LINUX)
+ dlopen("libGL.so.1", RTLD_LAZY | RTLD_GLOBAL);
+ glxewInit();
#endif
GpuProcess gpu_process;
diff --git a/chrome/gpu/gpu_thread.cc b/chrome/gpu/gpu_thread.cc
index d143cbc..4845b3a 100644
--- a/chrome/gpu/gpu_thread.cc
+++ b/chrome/gpu/gpu_thread.cc
@@ -9,14 +9,30 @@
#if defined(OS_WIN)
#include "chrome/gpu/gpu_view_win.h"
+#elif defined(OS_LINUX)
+#include "chrome/gpu/gpu_backing_store_glx_context.h"
+#include "chrome/gpu/gpu_view_x.h"
+
+#include <X11/Xutil.h> // Must be last.
#endif
GpuThread::GpuThread() {
+#if defined(OS_LINUX)
+ display_ = ::XOpenDisplay(NULL);
+#endif
}
GpuThread::~GpuThread() {
}
+#if defined(OS_LINUX)
+GpuBackingStoreGLXContext* GpuThread::GetGLXContext() {
+ if (!glx_context_.get())
+ glx_context_.reset(new GpuBackingStoreGLXContext(this));
+ return glx_context_.get();
+}
+#endif
+
void GpuThread::OnControlMessageReceived(const IPC::Message& msg) {
bool msg_is_ok = true;
IPC_BEGIN_MESSAGE_MAP_EX(GpuThread, msg, msg_is_ok)
@@ -25,13 +41,15 @@ void GpuThread::OnControlMessageReceived(const IPC::Message& msg) {
IPC_END_MESSAGE_MAP_EX()
}
-void GpuThread::OnNewRenderWidgetHostView(gfx::NativeViewId parent_window,
+void GpuThread::OnNewRenderWidgetHostView(GpuNativeWindowHandle parent_window,
int32 routing_id) {
+ // The GPUView class' lifetime is controlled by the host, which will send a
+ // message to destroy the GpuRWHView when necessary. So we don't manage the
+ // lifetime of this object.
#if defined(OS_WIN)
- // The class' lifetime is controlled by the host, which will send a message to
- // destroy the GpuRWHView when necessary. So we don't manage the lifetime
- // of this object.
new GpuViewWin(this, parent_window, routing_id);
+#elif defined(OS_LINUX)
+ new GpuViewX(this, parent_window, routing_id);
#else
NOTIMPLEMENTED();
#endif
diff --git a/chrome/gpu/gpu_thread.h b/chrome/gpu/gpu_thread.h
index 3f25b00..8e8300d8 100644
--- a/chrome/gpu/gpu_thread.h
+++ b/chrome/gpu/gpu_thread.h
@@ -7,21 +7,40 @@
#include "app/gfx/native_widget_types.h"
#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "build/build_config.h"
#include "chrome/common/child_thread.h"
+#include "chrome/common/gpu_native_window_handle.h"
+#include "chrome/gpu/x_util.h"
+
+#if defined(OS_LINUX)
+class GpuBackingStoreGLXContext;
+#endif
class GpuThread : public ChildThread {
public:
GpuThread();
~GpuThread();
+#if defined(OS_LINUX)
+ GpuBackingStoreGLXContext* GetGLXContext();
+
+ Display* display() const { return display_; }
+#endif
+
private:
// ChildThread overrides.
virtual void OnControlMessageReceived(const IPC::Message& msg);
// Message handlers.
- void OnNewRenderWidgetHostView(gfx::NativeViewId parent_window,
+ void OnNewRenderWidgetHostView(GpuNativeWindowHandle parent_window,
int32 routing_id);
+#if defined(OS_LINUX)
+ Display* display_;
+ scoped_ptr<GpuBackingStoreGLXContext> glx_context_;
+#endif
+
DISALLOW_COPY_AND_ASSIGN(GpuThread);
};
diff --git a/chrome/gpu/gpu_view_win.cc b/chrome/gpu/gpu_view_win.cc
index e6233a6..091c1a1 100644
--- a/chrome/gpu/gpu_view_win.cc
+++ b/chrome/gpu/gpu_view_win.cc
@@ -5,7 +5,7 @@
#include "chrome/gpu/gpu_view_win.h"
#include "chrome/common/gpu_messages.h"
-#include "chrome/gpu/gpu_backing_store.h"
+#include "chrome/gpu/gpu_backing_store_win.h"
#include "chrome/gpu/gpu_thread.h"
namespace {
@@ -22,13 +22,13 @@ void DrawResizeCorner(const RECT& dirty_rect, HDC dc) {
} // namespace
GpuViewWin::GpuViewWin(GpuThread* gpu_thread,
- gfx::NativeViewId parent_window,
+ HWND parent,
int32 routing_id)
: gpu_thread_(gpu_thread),
routing_id_(routing_id),
- parent_window_(gfx::NativeViewFromId(parent_window)) {
+ parent_(parent) {
gpu_thread_->AddRoute(routing_id_, this);
- Create(gfx::NativeViewFromId(parent_window));
+ Create(parent_);
SetWindowText(L"GPU window");
ShowWindow(SW_SHOW);
}
@@ -64,7 +64,7 @@ void GpuViewWin::DidScrollBackingStoreRect(int dx, int dy,
void GpuViewWin::OnNewBackingStore(int32 routing_id, const gfx::Size& size) {
backing_store_.reset(
- new GpuBackingStore(this, gpu_thread_, routing_id, size));
+ new GpuBackingStoreWin(this, gpu_thread_, routing_id, size));
MoveWindow(0, 0, size.width(), size.height(), TRUE);
}
diff --git a/chrome/gpu/gpu_view_win.h b/chrome/gpu/gpu_view_win.h
index 87d8f5d..f65dcb8 100644
--- a/chrome/gpu/gpu_view_win.h
+++ b/chrome/gpu/gpu_view_win.h
@@ -15,7 +15,7 @@
#include "base/scoped_ptr.h"
#include "ipc/ipc_channel.h"
-class GpuBackingStore;
+class GpuBackingStoreWin;
class GpuThread;
namespace gfx {
@@ -36,8 +36,8 @@ class GpuViewWin
GpuRenderWidgetHostViewWinTraits> {
public:
GpuViewWin(GpuThread* gpu_thread,
- gfx::NativeViewId parent_window,
- int32 routing_id);
+ HWND parent,
+ int32 routing_id);
~GpuViewWin();
// IPC::Channel::Listener implementation.
@@ -61,9 +61,9 @@ class GpuViewWin
GpuThread* gpu_thread_;
int32 routing_id_;
- HWND parent_window_;
+ HWND parent_;
- scoped_ptr<GpuBackingStore> backing_store_;
+ scoped_ptr<GpuBackingStoreWin> backing_store_;
DISALLOW_COPY_AND_ASSIGN(GpuViewWin);
};
diff --git a/chrome/gpu/gpu_view_x.cc b/chrome/gpu/gpu_view_x.cc
new file mode 100644
index 0000000..c8e4613
--- /dev/null
+++ b/chrome/gpu/gpu_view_x.cc
@@ -0,0 +1,96 @@
+// Copyright (c) 2010 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 "chrome/gpu/gpu_view_x.h"
+
+#include "base/scoped_ptr.h"
+#include "chrome/common/gpu_messages.h"
+#include "chrome/gpu/gpu_backing_store_glx.h"
+#include "chrome/gpu/gpu_backing_store_glx_context.h"
+#include "chrome/gpu/gpu_thread.h"
+
+// X stuff must be last since it does "#define Status int" which messes up some
+// of the header files we indirectly pull in.
+#include <GL/glxew.h>
+#include <X11/Xutil.h>
+
+GpuViewX::GpuViewX(GpuThread* gpu_thread,
+ XID parent,
+ int32 routing_id)
+ : gpu_thread_(gpu_thread),
+ routing_id_(routing_id),
+ window_(parent) {
+ gpu_thread_->AddRoute(routing_id_, this);
+}
+
+GpuViewX::~GpuViewX() {
+ gpu_thread_->RemoveRoute(routing_id_);
+ // TODO(brettw) may want to delete any dangling backing stores, or perhaps
+ // assert if one still exists.
+}
+
+GLXContext GpuViewX::BindContext() {
+ GLXContext ctx = gpu_thread_->GetGLXContext()->BindContext(window_);
+ CHECK(ctx);
+ return ctx;
+}
+
+void GpuViewX::OnMessageReceived(const IPC::Message& msg) {
+ IPC_BEGIN_MESSAGE_MAP(GpuViewX, msg)
+ IPC_MESSAGE_HANDLER(GpuMsg_NewBackingStore, OnNewBackingStore)
+ IPC_END_MESSAGE_MAP_EX()
+}
+
+void GpuViewX::OnChannelConnected(int32 peer_pid) {
+}
+
+void GpuViewX::OnChannelError() {
+ // TODO(brettw) do we need to delete ourselves now?
+}
+
+void GpuViewX::DidScrollBackingStoreRect(int dx, int dy,
+ const gfx::Rect& rect) {
+}
+
+void GpuViewX::Repaint() {
+ BindContext();
+
+ const gfx::Size& size = backing_store_->size();
+
+ glViewport(0, 0, size.width(), size.height());
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, backing_store_->texture_id());
+
+ // TODO(brettw) use vertex buffers.
+ // TODO(brettw) make this so we use the texture size rather than the whole
+ // area size so we don't stretch bitmaps.
+ glBegin(GL_QUADS);
+ glTexCoord2f(0.0f, 0.0f);
+ glVertex2f(-1.0, 1.0);
+
+ glTexCoord2f(0.0f, 1.0f);
+ glVertex2f(-1.0, -1.0);
+
+ glTexCoord2f(1.0f, 1.0f);
+ glVertex2f(1.0, -1.0);
+
+ glTexCoord2f(1.0f, 0.0f);
+ glVertex2f(1.0, 1.0);
+ glEnd();
+ DCHECK(glGetError() == GL_NO_ERROR);
+
+ // TODO(brettw) when we no longer stretch non-fitting bitmaps, we should
+ // paint white over any unpainted area here.
+
+ glXSwapBuffers(gpu_thread_->display(), window_);
+}
+
+void GpuViewX::OnNewBackingStore(int32 routing_id, const gfx::Size& size) {
+ backing_store_.reset(
+ new GpuBackingStoreGLX(this, gpu_thread_, routing_id, size));
+}
diff --git a/chrome/gpu/gpu_view_x.h b/chrome/gpu/gpu_view_x.h
new file mode 100644
index 0000000..29543a6
--- /dev/null
+++ b/chrome/gpu/gpu_view_x.h
@@ -0,0 +1,58 @@
+// Copyright (c) 2010 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.
+
+#ifndef CHROME_GPU_GPU_VIEW_X_H_
+#define CHROME_GPU_GPU_VIEW_X_H_
+
+#include "app/gfx/native_widget_types.h"
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "chrome/gpu/x_util.h"
+#include "ipc/ipc_channel.h"
+
+class GpuBackingStoreGLX;
+class GpuThread;
+
+namespace gfx {
+class Rect;
+class Size;
+}
+
+class GpuViewX
+ : public IPC::Channel::Listener {
+ public:
+ GpuViewX(GpuThread* gpu_thread,
+ XID parent,
+ int32 routing_id);
+ ~GpuViewX();
+
+ GpuThread* gpu_thread() const { return gpu_thread_; }
+
+ // Wrapper around GPUBackingStoreGLXContext using our current window.
+ GLXContext BindContext();
+
+ // IPC::Channel::Listener implementation.
+ virtual void OnMessageReceived(const IPC::Message& message);
+ virtual void OnChannelConnected(int32 peer_pid);
+ virtual void OnChannelError();
+
+ void DidScrollBackingStoreRect(int dx, int dy, const gfx::Rect& rect);
+
+ void Repaint();
+
+ private:
+ // IPC message handlers.
+ void OnNewBackingStore(int32 routing_id, const gfx::Size& size);
+
+ GpuThread* gpu_thread_;
+ int32 routing_id_;
+
+ XID window_;
+
+ scoped_ptr<GpuBackingStoreGLX> backing_store_;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuViewX);
+};
+
+#endif // CHROME_GPU_GPU_VIEW_X_H_
diff --git a/chrome/gpu/x_util.cc b/chrome/gpu/x_util.cc
new file mode 100644
index 0000000..3756f67
--- /dev/null
+++ b/chrome/gpu/x_util.cc
@@ -0,0 +1,11 @@
+// Copyright (c) 2010 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 "chrome/gpu/x_util.h"
+
+#include <X11/Xutil.h>
+
+void ScopedPtrXFree::operator()(void* x) const {
+ ::XFree(x);
+}
diff --git a/chrome/gpu/x_util.h b/chrome/gpu/x_util.h
new file mode 100644
index 0000000..bfdc983
--- /dev/null
+++ b/chrome/gpu/x_util.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2010 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.
+
+#ifndef CHROME_GPU_X_UTIL_H_
+#define CHROME_GPU_X_UTIL_H_
+
+// Some X-Windows specific stuff. This can be included on any platform, and will
+// be a NOP on non-Linux ones.
+
+#include "build/build_config.h"
+
+#if defined(OS_LINUX)
+
+// Forward declares ------------------------------------------------------------
+//
+// X Windows headers do a lot of evil stuff, like "#define Status int" which
+// will cause many problems when combined with our other header files (like
+// ones that define a class local enum called "Status."
+//
+// These definitions are not Kosher, but allow us to remove this dependency and
+// actually compile X at all.
+
+typedef unsigned long XID;
+
+extern "C" {
+
+typedef struct _XDisplay Display;
+typedef struct __GLXcontextRec *GLXContext;
+
+} // extern "C"
+
+// Utils -----------------------------------------------------------------------
+
+// scoped_ptr functor for XFree(). Use as follows:
+// scoped_ptr_mallox<XVisualInfo, ScopedPtrXFree> foo(...);
+// where "XVisualInfo" is any X type that is freed with XFree.
+class ScopedPtrXFree {
+ public:
+ void operator()(void* x) const;
+};
+
+#endif // OS_LINUX
+
+#endif // CHROME_GPU_X_UTIL_H_