diff options
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_ |