diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-26 05:15:42 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-26 05:15:42 +0000 |
commit | 7c4ea146bc033d89c1a0d527ae3d43b587a23cab (patch) | |
tree | 293c4da0b8fa44e5d4939c410434c51c8ffb872c | |
parent | 877cbee0688984a2a00ce074f981bdfb1e42abfa (diff) | |
download | chromium_src-7c4ea146bc033d89c1a0d527ae3d43b587a23cab.zip chromium_src-7c4ea146bc033d89c1a0d527ae3d43b587a23cab.tar.gz chromium_src-7c4ea146bc033d89c1a0d527ae3d43b587a23cab.tar.bz2 |
Create initial GPU backing store in the GPU process for X windows applications.
This gets the window from the RenderWidgetHostViewGtk and just does OpenGL
calls directly into it. There are a lot of bugs, especially around expose
events, which aren't really processed at all, and also tab teardown and
reparenting.
The new backing store defaults to off.
This does some refactoring of the existing Windows GPU process backing store
implementation to make some of it sharable by this Linux verion.
This removes some previously defunct in-process GL backing store code and moves
it to the GPU process.
This patch does some refactoring around how child processes are created using
zygoes or not. I found there were many places where a command line would be
checked with special logic to know whether to enable zygote code or not. I
tried to unify this so it could be computed once for each process type. This is
what most of the changed files in chrome/browser are related to.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/548112
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37088 0039d316-1c4b-4281-b951-d872f2087c98
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_ |