summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/app/chrome_dll_main.cc3
-rw-r--r--chrome/app/dummy_main_functions.cc4
-rw-r--r--chrome/browser/extensions/extension_tabs_module.cc47
-rw-r--r--chrome/browser/gpu_process_host.cc113
-rw-r--r--chrome/browser/gpu_process_host.h73
-rw-r--r--chrome/browser/gtk/tabs/dragged_tab_gtk.cc4
-rw-r--r--chrome/browser/renderer_host/backing_store.cc17
-rw-r--r--chrome/browser/renderer_host/backing_store.h192
-rw-r--r--chrome/browser/renderer_host/backing_store_glx.h74
-rw-r--r--chrome/browser/renderer_host/backing_store_mac.h56
-rw-r--r--chrome/browser/renderer_host/backing_store_mac.mm168
-rw-r--r--chrome/browser/renderer_host/backing_store_manager.cc26
-rw-r--r--chrome/browser/renderer_host/backing_store_manager.h24
-rw-r--r--chrome/browser/renderer_host/backing_store_proxy.cc90
-rw-r--r--chrome/browser/renderer_host/backing_store_proxy.h55
-rw-r--r--chrome/browser/renderer_host/backing_store_win.cc97
-rw-r--r--chrome/browser/renderer_host/backing_store_win.h52
-rw-r--r--chrome/browser/renderer_host/backing_store_x.cc284
-rw-r--r--chrome/browser/renderer_host/backing_store_x.h92
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.cc4
-rw-r--r--chrome/browser/renderer_host/gpu_view_host_win.cc36
-rw-r--r--chrome/browser/renderer_host/gpu_view_host_win.h39
-rw-r--r--chrome/browser/renderer_host/render_process_host.h6
-rw-r--r--chrome/browser/renderer_host/render_widget_host.cc36
-rw-r--r--chrome/browser/renderer_host/render_widget_host.h15
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_gtk.cc16
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.mm8
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_win.cc32
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_win.h12
-rw-r--r--chrome/browser/renderer_host/test/test_backing_store.cc31
-rw-r--r--chrome/browser/renderer_host/test/test_backing_store.h31
-rw-r--r--chrome/browser/renderer_host/test/test_render_view_host.cc4
-rw-r--r--chrome/browser/sandbox_policy.cc2
-rw-r--r--chrome/browser/tab_contents/thumbnail_generator.cc48
-rw-r--r--chrome/browser/views/tab_contents/tab_contents_view_win.cc2
-rwxr-xr-xchrome/chrome.gyp35
-rwxr-xr-xchrome/chrome_browser.gypi14
-rw-r--r--chrome/chrome_common.gypi2
-rwxr-xr-xchrome/chrome_tests.gypi2
-rw-r--r--chrome/common/child_process_host.h5
-rw-r--r--chrome/common/child_process_info.h3
-rw-r--r--chrome/common/chrome_switches.cc17
-rw-r--r--chrome/common/chrome_switches.h5
-rw-r--r--chrome/common/gpu_messages.h28
-rw-r--r--chrome/common/gpu_messages_internal.h59
-rw-r--r--chrome/gpu/gpu_backing_store.cc185
-rw-r--r--chrome/gpu/gpu_backing_store.h74
-rw-r--r--chrome/gpu/gpu_main.cc38
-rw-r--r--chrome/gpu/gpu_process.cc11
-rw-r--r--chrome/gpu/gpu_process.h19
-rw-r--r--chrome/gpu/gpu_thread.cc38
-rw-r--r--chrome/gpu/gpu_thread.h28
-rw-r--r--chrome/gpu/gpu_view_win.cc158
-rw-r--r--chrome/gpu/gpu_view_win.h102
-rw-r--r--ipc/ipc_message_utils.h2
55 files changed, 2067 insertions, 551 deletions
diff --git a/chrome/app/chrome_dll_main.cc b/chrome/app/chrome_dll_main.cc
index 8ef4314..b15e044 100644
--- a/chrome/app/chrome_dll_main.cc
+++ b/chrome/app/chrome_dll_main.cc
@@ -86,6 +86,7 @@
extern int BrowserMain(const MainFunctionParams&);
extern int RendererMain(const MainFunctionParams&);
+extern int GpuMain(const MainFunctionParams&);
extern int PluginMain(const MainFunctionParams&);
extern int WorkerMain(const MainFunctionParams&);
extern int NaClMain(const MainFunctionParams&);
@@ -671,6 +672,8 @@ int ChromeMain(int argc, char** argv) {
rv = PluginMain(main_params);
} else if (process_type == switches::kUtilityProcess) {
rv = UtilityMain(main_params);
+ } else if (process_type == switches::kGpuProcess) {
+ rv = GpuMain(main_params);
} else if (process_type == switches::kProfileImportProcess) {
#if defined(OS_MACOSX)
rv = ProfileImportMain(main_params);
diff --git a/chrome/app/dummy_main_functions.cc b/chrome/app/dummy_main_functions.cc
index fa066ca..192720e 100644
--- a/chrome/app/dummy_main_functions.cc
+++ b/chrome/app/dummy_main_functions.cc
@@ -42,3 +42,7 @@ int NaClBrokerMain(const MainFunctionParams& parameters) {
int DiagnosticsMain(const CommandLine& command_line) {
return 1;
}
+
+int GpuMain(const MainFunctionParams&) {
+ return ResultCodes::BAD_PROCESS_TYPE;
+}
diff --git a/chrome/browser/extensions/extension_tabs_module.cc b/chrome/browser/extensions/extension_tabs_module.cc
index edfd5f5..aac6081 100644
--- a/chrome/browser/extensions/extension_tabs_module.cc
+++ b/chrome/browser/extensions/extension_tabs_module.cc
@@ -765,55 +765,18 @@ bool CaptureVisibleTabFunction::RunImpl() {
// Build the image of a tab's contents out of a backing store.
void CaptureVisibleTabFunction::CaptureSnapshotFromBackingStore(
BackingStore* backing_store) {
- SkBitmap screen_capture;
-#if defined(OS_WIN)
skia::PlatformCanvas temp_canvas;
- if (!temp_canvas.initialize(backing_store->size().width(),
- backing_store->size().height(), true)) {
+ if (!backing_store->CopyFromBackingStore(gfx::Rect(gfx::Point(0, 0),
+ backing_store->size()),
+ &temp_canvas)) {
error_ = ExtensionErrorUtils::FormatErrorMessage(
keys::kInternalVisibleTabCaptureError, "");
SendResponse(false);
return;
}
- HDC temp_dc = temp_canvas.beginPlatformPaint();
- BitBlt(temp_dc,
- 0, 0, backing_store->size().width(), backing_store->size().height(),
- backing_store->hdc(), 0, 0, SRCCOPY);
- temp_canvas.endPlatformPaint();
-
- screen_capture = temp_canvas.getTopPlatformDevice().accessBitmap(false);
-#elif defined(OS_MACOSX)
- skia::PlatformCanvas temp_canvas;
- if (!temp_canvas.initialize(backing_store->size().width(),
- backing_store->size().height(), true)) {
- error_ = ExtensionErrorUtils::FormatErrorMessage(
- keys::kInternalVisibleTabCaptureError, "");
- SendResponse(false);
- return;
- }
- CGContextRef temp_context = temp_canvas.beginPlatformPaint();
- CGContextSaveGState(temp_context);
- CGContextTranslateCTM(temp_context, 0.0, backing_store->size().height());
- CGContextScaleCTM(temp_context, 1.0, -1.0);
- CGContextDrawLayerAtPoint(temp_context, CGPointMake(0.0, 0.0),
- backing_store->cg_layer());
- CGContextRestoreGState(temp_context);
- temp_canvas.endPlatformPaint();
-
- screen_capture = temp_canvas.getTopPlatformDevice().accessBitmap(false);
-#elif defined(OS_LINUX)
- screen_capture = backing_store->PaintRectToBitmap(
- gfx::Rect(0, 0, backing_store->size().width(),
- backing_store->size().height()));
-#else
- // TODO(port)
- error_ = keys::kNotImplementedError;
- SendResponse(false);
- return;
-#endif
-
- SendResultFromBitmap(screen_capture);
+ SendResultFromBitmap(
+ temp_canvas.getTopPlatformDevice().accessBitmap(false));
}
// If a backing store was not available in CaptureVisibleTabFunction::RunImpl,
diff --git a/chrome/browser/gpu_process_host.cc b/chrome/browser/gpu_process_host.cc
new file mode 100644
index 0000000..905f5c7
--- /dev/null
+++ b/chrome/browser/gpu_process_host.cc
@@ -0,0 +1,113 @@
+// 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/gpu_process_host.h"
+
+#include "base/command_line.h"
+#include "base/singleton.h"
+#include "base/thread.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/child_process_launcher.h"
+#include "chrome/common/child_process_host.h"
+#include "chrome/common/child_process_info.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/gpu_messages.h"
+#include "ipc/ipc_switches.h"
+
+GpuProcessHost::GpuProcessHost() : last_routing_id_(1) {
+ FilePath exe_path = ChildProcessHost::GetChildPath();
+ if (exe_path.empty())
+ return;
+
+ std::string channel_id = ChildProcessInfo::GenerateRandomChannelID(this);
+ channel_.reset(new IPC::ChannelProxy(
+ channel_id,
+ IPC::Channel::MODE_SERVER,
+ this,
+ NULL, // No filter (for now).
+ g_browser_process->io_thread()->message_loop()));
+
+ CommandLine* cmd_line = new CommandLine(exe_path);
+ cmd_line->AppendSwitchWithValue(switches::kProcessType,
+ switches::kGpuProcess);
+ cmd_line->AppendSwitchWithValue(switches::kProcessChannelID,
+ ASCIIToWide(channel_id));
+
+ // Spawn the child process asynchronously to avoid blocking the UI thread.
+ child_process_.reset(new ChildProcessLauncher(
+#if defined(OS_WIN)
+ FilePath(),
+#elif defined(POSIX)
+ base::environment_vector(),
+ channel_->GetClientFileDescriptor(),
+#endif
+ cmd_line,
+ this));
+}
+
+GpuProcessHost::~GpuProcessHost() {
+}
+
+// static
+GpuProcessHost* GpuProcessHost::Get() {
+ GpuProcessHost* host = Singleton<GpuProcessHost>::get();
+ if (!host->child_process_.get())
+ return NULL; // Failed to init.
+ return host;
+}
+
+int32 GpuProcessHost::GetNextRoutingId() {
+ return ++last_routing_id_;
+}
+
+int32 GpuProcessHost::NewRenderWidgetHostView(gfx::NativeViewId parent) {
+ int32 routing_id = GetNextRoutingId();
+ Send(new GpuMsg_NewRenderWidgetHostView(parent, routing_id));
+ return routing_id;
+}
+
+bool GpuProcessHost::Send(IPC::Message* msg) {
+ if (!channel_.get()) {
+ delete msg;
+ return false;
+ }
+
+ if (child_process_.get() && child_process_->IsStarting()) {
+ queued_messages_.push(msg);
+ return true;
+ }
+
+ return channel_->Send(msg);
+}
+
+void GpuProcessHost::OnMessageReceived(const IPC::Message& message) {
+ if (message.routing_id() == MSG_ROUTING_CONTROL) {
+ // We don't currently have any control messages.
+ // OnControlMessageReceived(message);
+ } else {
+ router_.OnMessageReceived(message);
+ }
+}
+
+void GpuProcessHost::OnChannelConnected(int32 peer_pid) {
+}
+
+void GpuProcessHost::OnChannelError() {
+}
+
+void GpuProcessHost::OnProcessLaunched() {
+ while (!queued_messages_.empty()) {
+ Send(queued_messages_.front());
+ queued_messages_.pop();
+ }
+}
+
+void GpuProcessHost::AddRoute(int32 routing_id,
+ IPC::Channel::Listener* listener) {
+ router_.AddRoute(routing_id, listener);
+}
+
+void GpuProcessHost::RemoveRoute(int32 routing_id) {
+ router_.RemoveRoute(routing_id);
+}
diff --git a/chrome/browser/gpu_process_host.h b/chrome/browser/gpu_process_host.h
new file mode 100644
index 0000000..1856182
--- /dev/null
+++ b/chrome/browser/gpu_process_host.h
@@ -0,0 +1,73 @@
+// 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_GPU_PROCESS_HOST_H_
+#define CHROME_BROWSER_GPU_PROCESS_HOST_H_
+
+#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/message_router.h"
+#include "ipc/ipc_channel_proxy.h"
+
+class ChildProcessLauncher;
+
+class GpuProcessHost : public IPC::Channel::Sender,
+ public IPC::Channel::Listener,
+ public ChildProcessLauncher::Client {
+ public:
+ // Getter for the singleton. This will return NULL on failure.
+ static GpuProcessHost* Get();
+
+ int32 GetNextRoutingId();
+
+ // Creates the new remote view and returns the routing ID for the view, or 0
+ // on failure.
+ int32 NewRenderWidgetHostView(gfx::NativeViewId parent);
+
+ // IPC::Channel::Sender implementation.
+ virtual bool Send(IPC::Message* msg);
+
+ // IPC::Channel::Listener implementation.
+ virtual void OnMessageReceived(const IPC::Message& message);
+ virtual void OnChannelConnected(int32 peer_pid);
+ virtual void OnChannelError();
+
+ // ChildProcessLauncher::Client implementation.
+ virtual void OnProcessLaunched();
+
+ // See documentation on MessageRouter for AddRoute and RemoveRoute
+ void AddRoute(int32 routing_id, IPC::Channel::Listener* listener);
+ void RemoveRoute(int32 routing_id);
+
+ private:
+ friend struct DefaultSingletonTraits<GpuProcessHost>;
+
+ GpuProcessHost();
+ virtual ~GpuProcessHost();
+
+ scoped_ptr<ChildProcessLauncher> child_process_;
+
+ // A proxy for our IPC::Channel that lives on the IO thread (see
+ // browser_process.h). This will be NULL if the class failed to initialize.
+ scoped_ptr<IPC::ChannelProxy> channel_;
+
+ int last_routing_id_;
+
+ MessageRouter router_;
+
+ // Messages we queue while waiting for the process handle. We queue them here
+ // instead of in the channel so that we ensure they're sent after init related
+ // messages that are sent once the process handle is available. This is
+ // because the queued messages may have dependencies on the init messages.
+ std::queue<IPC::Message*> queued_messages_;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuProcessHost);
+};
+
+#endif // CHROME_BROWSER_GPU_PROCESS_HOST_H_
diff --git a/chrome/browser/gtk/tabs/dragged_tab_gtk.cc b/chrome/browser/gtk/tabs/dragged_tab_gtk.cc
index fce118d..afaedea 100644
--- a/chrome/browser/gtk/tabs/dragged_tab_gtk.cc
+++ b/chrome/browser/gtk/tabs/dragged_tab_gtk.cc
@@ -13,7 +13,7 @@
#include "app/l10n_util.h"
#include "chrome/browser/browser_theme_provider.h"
#include "chrome/browser/profile.h"
-#include "chrome/browser/renderer_host/backing_store.h"
+#include "chrome/browser/renderer_host/backing_store_x.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tabs/tab_strip_model.h"
#include "chrome/browser/gtk/tabs/tab_renderer_gtk.h"
@@ -301,7 +301,7 @@ gboolean DraggedTabGtk::OnExposeEvent(GtkWidget* widget,
dragged_tab->data_source_->render_view_host()->GetBackingStore(false);
if (backing_store && !dragged_tab->attached_) {
// This leaves room for the border.
- backing_store->PaintToRect(
+ static_cast<BackingStoreX*>(backing_store)->PaintToRect(
gfx::Rect(kDragFrameBorderSize, tab_height,
widget->allocation.width - kTwiceDragFrameBorderSize,
widget->allocation.height - tab_height -
diff --git a/chrome/browser/renderer_host/backing_store.cc b/chrome/browser/renderer_host/backing_store.cc
new file mode 100644
index 0000000..feebac3
--- /dev/null
+++ b/chrome/browser/renderer_host/backing_store.cc
@@ -0,0 +1,17 @@
+// 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"
+
+BackingStore::BackingStore(RenderWidgetHost* widget, const gfx::Size& size)
+ : render_widget_host_(widget),
+ size_(size) {
+}
+
+BackingStore::~BackingStore() {
+}
+
+size_t BackingStore::MemorySize() {
+ return size_.GetArea() * 4;
+}
diff --git a/chrome/browser/renderer_host/backing_store.h b/chrome/browser/renderer_host/backing_store.h
index 28640ba..a60adc2 100644
--- a/chrome/browser/renderer_host/backing_store.h
+++ b/chrome/browser/renderer_host/backing_store.h
@@ -1,185 +1,81 @@
-// Copyright (c) 2006-2008 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_H_
#define CHROME_BROWSER_RENDERER_HOST_BACKING_STORE_H_
+#include <vector>
+
#include "base/basictypes.h"
-#include "base/gfx/rect.h"
#include "base/gfx/size.h"
#include "base/process.h"
-#include "build/build_config.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#elif defined(OS_MACOSX)
-#include "base/scoped_cftyperef.h"
-#include "skia/ext/platform_canvas.h"
-#elif defined(OS_LINUX)
-#include "chrome/common/x11_util.h"
-#endif
+#include "chrome/common/transport_dib.h"
+class RenderProcessHost;
class RenderWidgetHost;
-class SkBitmap;
-class TransportDIB;
-typedef struct _GdkDrawable GdkDrawable;
-// BackingStore ----------------------------------------------------------------
+namespace gfx {
+class Rect;
+}
+
+namespace skia {
+class PlatformCanvas;
+}
// Represents a backing store for the pixels in a RenderWidgetHost.
class BackingStore {
public:
-#if defined(OS_WIN) || defined(OS_MACOSX)
- BackingStore(RenderWidgetHost* widget, const gfx::Size& size);
-#elif defined(OS_LINUX)
- // 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.
- BackingStore(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
- BackingStore(RenderWidgetHost* widget, const gfx::Size& size);
-#endif
- ~BackingStore();
+ virtual ~BackingStore();
RenderWidgetHost* render_widget_host() const { return render_widget_host_; }
const gfx::Size& size() { return size_; }
- // The number of bytes that this backing store consumes. This should roughly
- // be size_.GetArea() * bytes per pixel.
- size_t MemorySize();
-
-#if defined(OS_WIN)
- HDC hdc() { return hdc_; }
-
- // Returns true if we should convert to the monitor profile when painting.
- static bool ColorManagementEnabled();
-#elif defined(OS_MACOSX)
- // A CGLayer that stores the contents of the backing store, cached in GPU
- // memory if possible.
- CGLayerRef cg_layer() { return cg_layer_; }
- // A CGBitmapContext that stores the contents of the backing store if the
- // corresponding Cocoa view has not been inserted into an NSWindow yet.
- CGContextRef cg_bitmap() { return cg_bitmap_; }
-
- // Paint the layer into a graphics context--if the target is a window,
- // this should be a GPU->GPU copy (and therefore very fast).
- void PaintToRect(const gfx::Rect& dest_rect, CGContextRef target);
-#elif defined(OS_LINUX)
- 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);
-#endif
-
-#if defined(TOOLKIT_GTK)
- // Paint the backing store into the target's |dest_rect|.
- void PaintToRect(const gfx::Rect& dest_rect, GdkDrawable* target);
-#endif
+ // The number of bytes that this backing store consumes. The default
+ // implementation just assumes there's 32 bits per pixel over the current
+ // size of the screen. Implementations may override this if they have more
+ // information about the color depth.
+ virtual size_t MemorySize();
// Paints the bitmap from the renderer onto the backing store. bitmap_rect
- // gives the location of bitmap, and copy_rect specifies the subregion of
+ // gives the location of bitmap, and copy_rects specifies the subregion(s) of
// the backingstore to be painted from the bitmap.
- void PaintRect(base::ProcessHandle process,
- TransportDIB* bitmap,
- const gfx::Rect& bitmap_rect,
- const gfx::Rect& copy_rect);
+ //
+ // The value placed into |*painted_synchronously| indicates if the paint was
+ // completed synchronously and the TransportDIB can be freed. False means that
+ // the backing store may still be using the transport DIB and it will manage
+ // notifying the RenderWidgetHost that it's done with it via
+ // DonePaintingToBackingStore().
+ virtual void PaintToBackingStore(
+ RenderProcessHost* process,
+ TransportDIB::Id bitmap,
+ const gfx::Rect& bitmap_rect,
+ const std::vector<gfx::Rect>& copy_rects,
+ bool* painted_synchronously) = 0;
+
+ // Extracts the gives subset of the backing store and copies it to the given
+ // PlatformCanvas. The PlatformCanvas should not be initialized. This function
+ // will call initialize() with the correct size. The return value indicates
+ // success.
+ virtual bool CopyFromBackingStore(const gfx::Rect& rect,
+ skia::PlatformCanvas* output) = 0;
// Scrolls the contents of clip_rect in the backing store by dx or dy (but dx
// and dy cannot both be non-zero).
- void ScrollRect(int dx, int dy,
- const gfx::Rect& clip_rect,
- const gfx::Size& view_size);
+ virtual void ScrollBackingStore(int dx, int dy,
+ const gfx::Rect& clip_rect,
+ const gfx::Size& view_size) = 0;
+ protected:
+ // Can only be constructed via subclasses.
+ BackingStore(RenderWidgetHost* widget, const gfx::Size& size);
private:
-#if defined(OS_MACOSX)
- // Creates a CGLayer associated with its owner view's window's graphics
- // context, sized properly for the backing store. Returns NULL if the owner
- // is not in a window with a CGContext. cg_layer_ is assigned this method's
- // result.
- CGLayerRef CreateCGLayer();
-
- // Creates a CGBitmapContext sized properly for the backing store. The
- // owner view need not be in a window. cg_bitmap_ is assigned this method's
- // result.
- CGContextRef CreateCGBitmapContext();
-#endif
-
// The owner of this backing store.
RenderWidgetHost* render_widget_host_;
// The size of the backing store.
gfx::Size size_;
-#if defined(OS_WIN)
- // The backing store dc.
- HDC hdc_;
- // Handle to the backing store dib.
- HANDLE backing_store_dib_;
- // Handle to the original bitmap in the dc.
- HANDLE original_bitmap_;
- // Number of bits per pixel of the screen.
- int color_depth_;
-#elif defined(OS_MACOSX)
- scoped_cftyperef<CGContextRef> cg_bitmap_;
- scoped_cftyperef<CGLayerRef> cg_layer_;
-#elif defined(OS_LINUX) && defined(USE_GL)
- 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_;
-
-#elif defined(OS_LINUX) && !defined(USE_GL)
- // Paints the bitmap from the renderer onto the backing store without
- // using Xrender to composite the pixmaps.
- void PaintRectWithoutXrender(TransportDIB* bitmap,
- const gfx::Rect& bitmap_rect,
- const gfx::Rect& copy_rect);
-
- // This is the connection to the X server where this backing store will be
- // displayed.
- Display* const display_;
- // What flavor, if any, MIT-SHM (X shared memory) support we have.
- const x11_util::SharedMemorySupport shared_memory_support_;
- // If this is true, then we can use Xrender to composite our pixmaps.
- const bool use_render_;
- // If |use_render_| is false, this is the number of bits-per-pixel for |depth|
- int pixmap_bpp_;
- // if |use_render_| is false, we need the Visual to get the RGB masks.
- void* const visual_;
- // This is the depth of the target window.
- const int visual_depth_;
- // The parent window (probably a GtkDrawingArea) for this backing store.
- const XID root_window_;
- // This is a handle to the server side pixmap which is our backing store.
- XID pixmap_;
- // This is the RENDER picture pointing at |pixmap_|.
- XID picture_;
- // This is a default graphic context, used in XCopyArea
- void* pixmap_gc_;
-#endif
-
DISALLOW_COPY_AND_ASSIGN(BackingStore);
};
diff --git a/chrome/browser/renderer_host/backing_store_glx.h b/chrome/browser/renderer_host/backing_store_glx.h
new file mode 100644
index 0000000..534c052
--- /dev/null
+++ b/chrome/browser/renderer_host/backing_store_glx.h
@@ -0,0 +1,74 @@
+// 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_mac.h b/chrome/browser/renderer_host/backing_store_mac.h
new file mode 100644
index 0000000..3d9e793
--- /dev/null
+++ b/chrome/browser/renderer_host/backing_store_mac.h
@@ -0,0 +1,56 @@
+// 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_MAC_H_
+#define CHROME_BROWSER_RENDERER_HOST_BACKING_STORE_MAC_H_
+
+#include "base/basictypes.h"
+#include "base/scoped_cftyperef.h"
+#include "chrome/browser/renderer_host/backing_store.h"
+
+class BackingStoreMac : public BackingStore {
+ public:
+ BackingStoreMac(RenderWidgetHost* widget, const gfx::Size& size);
+ virtual ~BackingStoreMac();
+
+ // A CGLayer that stores the contents of the backing store, cached in GPU
+ // memory if possible.
+ CGLayerRef cg_layer() { return cg_layer_; }
+
+ // A CGBitmapContext that stores the contents of the backing store if the
+ // corresponding Cocoa view has not been inserted into an NSWindow yet.
+ CGContextRef cg_bitmap() { return cg_bitmap_; }
+
+ // BackingStore implementation.
+ virtual void PaintToBackingStore(
+ RenderProcessHost* process,
+ TransportDIB::Id bitmap,
+ const gfx::Rect& bitmap_rect,
+ const std::vector<gfx::Rect>& copy_rects,
+ bool* painted_synchronously);
+ virtual bool CopyFromBackingStore(const gfx::Rect& rect,
+ skia::PlatformCanvas* output);
+ virtual void ScrollBackingStore(int dx, int dy,
+ const gfx::Rect& clip_rect,
+ const gfx::Size& view_size);
+
+ private:
+ // Creates a CGLayer associated with its owner view's window's graphics
+ // context, sized properly for the backing store. Returns NULL if the owner
+ // is not in a window with a CGContext. cg_layer_ is assigned this method's
+ // result.
+ CGLayerRef CreateCGLayer();
+
+ // Creates a CGBitmapContext sized properly for the backing store. The
+ // owner view need not be in a window. cg_bitmap_ is assigned this method's
+ // result.
+ CGContextRef CreateCGBitmapContext();
+
+ scoped_cftyperef<CGContextRef> cg_bitmap_;
+ scoped_cftyperef<CGLayerRef> cg_layer_;
+
+ DISALLOW_COPY_AND_ASSIGN(BackingStoreMac);
+};
+
+#endif // CHROME_BROWSER_RENDERER_HOST_BACKING_STORE_MAC_H_
diff --git a/chrome/browser/renderer_host/backing_store_mac.mm b/chrome/browser/renderer_host/backing_store_mac.mm
index 0b8fa6e..1324593 100644
--- a/chrome/browser/renderer_host/backing_store_mac.mm
+++ b/chrome/browser/renderer_host/backing_store_mac.mm
@@ -1,15 +1,16 @@
-// Copyright (c) 2006-2008 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.
#import <Cocoa/Cocoa.h>
-#include "chrome/browser/renderer_host/backing_store.h"
-#include "chrome/browser/renderer_host/render_widget_host.h"
-#include "chrome/browser/renderer_host/render_widget_host_view.h"
+#include "chrome/browser/renderer_host/backing_store_mac.h"
#include "base/logging.h"
#include "base/mac_util.h"
+#include "chrome/browser/renderer_host/render_process_host.h"
+#include "chrome/browser/renderer_host/render_widget_host.h"
+#include "chrome/browser/renderer_host/render_widget_host_view.h"
#include "chrome/common/transport_dib.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -22,9 +23,9 @@
// allows acclerated drawing into the layer and lets scrolling and such happen
// all or mostly on the GPU, which is good for performance.
-BackingStore::BackingStore(RenderWidgetHost* widget, const gfx::Size& size)
- : render_widget_host_(widget),
- size_(size) {
+BackingStoreMac::BackingStoreMac(RenderWidgetHost* widget,
+ const gfx::Size& size)
+ : BackingStore(widget, size) {
cg_layer_.reset(CreateCGLayer());
if (!cg_layer_) {
// The view isn't in a window yet. Use a CGBitmapContext for now.
@@ -32,23 +33,27 @@ BackingStore::BackingStore(RenderWidgetHost* widget, const gfx::Size& size)
}
}
-BackingStore::~BackingStore() {
+BackingStoreMac::~BackingStoreMac() {
}
-size_t BackingStore::MemorySize() {
- // Estimate memory usage as 4 bytes per pixel.
- return size_.GetArea() * 4;
-}
+void BackingStoreMac::PaintToBackingStore(
+ RenderProcessHost* process,
+ TransportDIB::Id bitmap,
+ const gfx::Rect& bitmap_rect,
+ const std::vector<gfx::Rect>& copy_rects,
+ bool* painted_synchronously) {
+ // Our paints are always synchronous and the caller can free the TransportDIB,
+ // even on failure.
+ *painted_synchronously = true;
-// Paint the contents of a TransportDIB into a rectangle of our CGLayer
-void BackingStore::PaintRect(base::ProcessHandle process,
- TransportDIB* bitmap,
- const gfx::Rect& bitmap_rect,
- const gfx::Rect& copy_rect) {
DCHECK_NE(static_cast<bool>(cg_layer()), static_cast<bool>(cg_bitmap()));
+ TransportDIB* dib = process->GetTransportDIB(bitmap);
+ if (!dib)
+ return;
+
scoped_cftyperef<CGDataProviderRef> data_provider(
- CGDataProviderCreateWithData(NULL, bitmap->memory(),
+ CGDataProviderCreateWithData(NULL, dib->memory(),
bitmap_rect.width() * bitmap_rect.height() * 4, NULL));
scoped_cftyperef<CGImageRef> bitmap_image(
@@ -57,51 +62,71 @@ void BackingStore::PaintRect(base::ProcessHandle process,
kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
data_provider, NULL, false, kCGRenderingIntentDefault));
- // Only the subpixels given by copy_rect have pixels to copy.
- scoped_cftyperef<CGImageRef> image(
- CGImageCreateWithImageInRect(bitmap_image, CGRectMake(
- copy_rect.x() - bitmap_rect.x(),
- copy_rect.y() - bitmap_rect.y(),
- copy_rect.width(),
- copy_rect.height())));
-
- if (!cg_layer()) {
- // The view may have moved to a window. Try to get a CGLayer.
- cg_layer_.reset(CreateCGLayer());
- if (cg_layer()) {
- // now that we have a layer, copy the cached image into it
- scoped_cftyperef<CGImageRef> bitmap_image(
- CGBitmapContextCreateImage(cg_bitmap_));
- CGContextDrawImage(CGLayerGetContext(cg_layer()),
- CGRectMake(0, 0, size().width(), size().height()),
- bitmap_image);
- // Discard the cache bitmap, since we no longer need it.
- cg_bitmap_.reset(NULL);
+ for (size_t i = 0; i < copy_rects.size(); i++) {
+ const gfx::Rect& copy_rect = copy_rects[i];
+
+ // Only the subpixels given by copy_rect have pixels to copy.
+ scoped_cftyperef<CGImageRef> image(
+ CGImageCreateWithImageInRect(bitmap_image, CGRectMake(
+ copy_rect.x() - bitmap_rect.x(),
+ copy_rect.y() - bitmap_rect.y(),
+ copy_rect.width(),
+ copy_rect.height())));
+
+ if (!cg_layer()) {
+ // The view may have moved to a window. Try to get a CGLayer.
+ cg_layer_.reset(CreateCGLayer());
+ if (cg_layer()) {
+ // now that we have a layer, copy the cached image into it
+ scoped_cftyperef<CGImageRef> bitmap_image(
+ CGBitmapContextCreateImage(cg_bitmap_));
+ CGContextDrawImage(CGLayerGetContext(cg_layer()),
+ CGRectMake(0, 0, size().width(), size().height()),
+ bitmap_image);
+ // Discard the cache bitmap, since we no longer need it.
+ cg_bitmap_.reset(NULL);
+ }
}
- }
- DCHECK_NE(static_cast<bool>(cg_layer()), static_cast<bool>(cg_bitmap()));
+ DCHECK_NE(static_cast<bool>(cg_layer()), static_cast<bool>(cg_bitmap()));
- if (cg_layer()) {
- // The CGLayer's origin is in the lower left, but flipping the CTM would
- // cause the image to get drawn upside down. So we move the rectangle
- // to the right position before drawing the image.
- CGContextRef layer = CGLayerGetContext(cg_layer());
- gfx::Rect paint_rect = copy_rect;
- paint_rect.set_y(size_.height() - copy_rect.bottom());
- CGContextDrawImage(layer, paint_rect.ToCGRect(), image);
- } else {
- // The layer hasn't been created yet, so draw into the cache bitmap.
- gfx::Rect paint_rect = copy_rect;
- paint_rect.set_y(size_.height() - copy_rect.bottom());
- CGContextDrawImage(cg_bitmap_, paint_rect.ToCGRect(), image);
+ if (cg_layer()) {
+ // The CGLayer's origin is in the lower left, but flipping the CTM would
+ // cause the image to get drawn upside down. So we move the rectangle
+ // to the right position before drawing the image.
+ CGContextRef layer = CGLayerGetContext(cg_layer());
+ gfx::Rect paint_rect = copy_rect;
+ paint_rect.set_y(size().height() - copy_rect.bottom());
+ CGContextDrawImage(layer, paint_rect.ToCGRect(), image);
+ } else {
+ // The layer hasn't been created yet, so draw into the cache bitmap.
+ gfx::Rect paint_rect = copy_rect;
+ paint_rect.set_y(size().height() - copy_rect.bottom());
+ CGContextDrawImage(cg_bitmap_, paint_rect.ToCGRect(), image);
+ }
}
}
+bool BackingStoreMac::CopyFromBackingStore(const gfx::Rect& rect,
+ skia::PlatformCanvas* output) {
+ if (!output->initialize(rect.width(), rect.height(), true))
+ return false;
+
+ CGContextRef temp_context = output->beginPlatformPaint();
+ CGContextSaveGState(temp_context);
+ CGContextTranslateCTM(temp_context, 0.0, size().height());
+ CGContextScaleCTM(temp_context, 1.0, -1.0);
+ CGContextDrawLayerAtPoint(temp_context, CGPointMake(rect.x(), rect.y()),
+ cg_layer());
+ CGContextRestoreGState(temp_context);
+ output->endPlatformPaint();
+ return true;
+}
+
// Scroll the contents of our CGLayer
-void BackingStore::ScrollRect(int dx, int dy,
- const gfx::Rect& clip_rect,
- const gfx::Size& view_size) {
+void BackingStoreMac::ScrollBackingStore(int dx, int dy,
+ const gfx::Rect& clip_rect,
+ const gfx::Size& view_size) {
DCHECK_NE(static_cast<bool>(cg_layer()), static_cast<bool>(cg_bitmap()));
// "Scroll" the contents of the layer by creating a new CGLayer,
@@ -114,10 +139,10 @@ void BackingStore::ScrollRect(int dx, int dy,
// translated by the scroll.)
// We assume |clip_rect| is contained within the backing store.
- DCHECK(clip_rect.bottom() <= size_.height());
- DCHECK(clip_rect.right() <= size_.width());
+ DCHECK(clip_rect.bottom() <= size().height());
+ DCHECK(clip_rect.right() <= size().width());
- if ((dx || dy) && abs(dx) < size_.width() && abs(dy) < size_.height()) {
+ if ((dx || dy) && abs(dx) < size().width() && abs(dy) < size().height()) {
if (cg_layer()) {
scoped_cftyperef<CGLayerRef> new_layer(CreateCGLayer());
@@ -127,10 +152,11 @@ void BackingStore::ScrollRect(int dx, int dy,
CGContextRef layer = CGLayerGetContext(new_layer);
CGContextDrawLayerAtPoint(layer, CGPointMake(0, 0), cg_layer());
CGContextSaveGState(layer);
- CGContextClipToRect(layer, CGRectMake(clip_rect.x(),
- size_.height() - clip_rect.bottom(),
- clip_rect.width(),
- clip_rect.height()));
+ CGContextClipToRect(layer,
+ CGRectMake(clip_rect.x(),
+ size().height() - clip_rect.bottom(),
+ clip_rect.width(),
+ clip_rect.height()));
CGContextDrawLayerAtPoint(layer, CGPointMake(dx, -dy), cg_layer());
CGContextRestoreGState(layer);
cg_layer_.swap(new_layer);
@@ -140,16 +166,16 @@ void BackingStore::ScrollRect(int dx, int dy,
scoped_cftyperef<CGImageRef> bitmap_image(
CGBitmapContextCreateImage(cg_bitmap_));
CGContextDrawImage(new_bitmap,
- CGRectMake(0, 0, size_.width(), size_.height()),
+ CGRectMake(0, 0, size().width(), size().height()),
bitmap_image);
CGContextSaveGState(new_bitmap);
CGContextClipToRect(new_bitmap,
CGRectMake(clip_rect.x(),
- size_.height() - clip_rect.bottom(),
+ size().height() - clip_rect.bottom(),
clip_rect.width(),
clip_rect.height()));
CGContextDrawImage(new_bitmap,
- CGRectMake(dx, -dy, size_.width(), size_.height()),
+ CGRectMake(dx, -dy, size().width(), size().height()),
bitmap_image);
CGContextRestoreGState(new_bitmap);
cg_bitmap_.swap(new_bitmap);
@@ -157,7 +183,7 @@ void BackingStore::ScrollRect(int dx, int dy,
}
}
-CGLayerRef BackingStore::CreateCGLayer() {
+CGLayerRef BackingStoreMac::CreateCGLayer() {
// The CGLayer should be optimized for drawing into the containing window,
// so extract a CGContext corresponding to the window to be passed to
// CGLayerCreateWithContext.
@@ -176,19 +202,19 @@ CGLayerRef BackingStore::CreateCGLayer() {
DCHECK(cg_context);
CGLayerRef layer = CGLayerCreateWithContext(cg_context,
- size_.ToCGSize(),
+ size().ToCGSize(),
NULL);
DCHECK(layer);
return layer;
}
-CGContextRef BackingStore::CreateCGBitmapContext() {
+CGContextRef BackingStoreMac::CreateCGBitmapContext() {
// A CGBitmapContext serves as a stand-in for the layer before the view is
// in a containing window.
CGContextRef context = CGBitmapContextCreate(NULL,
- size_.width(), size_.height(),
- 8, size_.width() * 4,
+ size().width(), size().height(),
+ 8, size().width() * 4,
mac_util::GetSystemColorSpace(),
kCGImageAlphaPremultipliedFirst |
kCGBitmapByteOrder32Host);
diff --git a/chrome/browser/renderer_host/backing_store_manager.cc b/chrome/browser/renderer_host/backing_store_manager.cc
index 4e21d04..39149f2 100644
--- a/chrome/browser/renderer_host/backing_store_manager.cc
+++ b/chrome/browser/renderer_host/backing_store_manager.cc
@@ -1,4 +1,4 @@
-// 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.
@@ -175,14 +175,17 @@ BackingStore* BackingStoreManager::GetBackingStore(
}
// static
-BackingStore* BackingStoreManager::PrepareBackingStore(
+void BackingStoreManager::PrepareBackingStore(
RenderWidgetHost* host,
const gfx::Size& backing_store_size,
- base::ProcessHandle process_handle,
- TransportDIB* bitmap,
+ TransportDIB::Id bitmap,
const gfx::Rect& bitmap_rect,
const std::vector<gfx::Rect>& copy_rects,
- bool* needs_full_paint) {
+ bool* needs_full_paint,
+ bool* painted_synchronously) {
+ // Default to declaring we're done using the transport DIB so it can be freed.
+ *painted_synchronously = true;
+
BackingStore* backing_store = GetBackingStore(host, backing_store_size);
if (!backing_store) {
// We need to get Webkit to generate a new paint here, as we
@@ -194,19 +197,14 @@ BackingStore* BackingStoreManager::PrepareBackingStore(
*needs_full_paint = true;
// Makes no sense to paint the transport dib if we are going
// to request a full paint.
- return NULL;
+ return;
}
backing_store = CreateBackingStore(host, backing_store_size);
}
- DCHECK(backing_store != NULL);
-
- for (size_t i = 0; i < copy_rects.size(); ++i) {
- backing_store->PaintRect(process_handle, bitmap, bitmap_rect,
- copy_rects[i]);
- }
-
- return backing_store;
+ backing_store->PaintToBackingStore(host->process(), bitmap,
+ bitmap_rect, copy_rects,
+ painted_synchronously);
}
// static
diff --git a/chrome/browser/renderer_host/backing_store_manager.h b/chrome/browser/renderer_host/backing_store_manager.h
index 847d8a1..96edd93 100644
--- a/chrome/browser/renderer_host/backing_store_manager.h
+++ b/chrome/browser/renderer_host/backing_store_manager.h
@@ -1,4 +1,4 @@
-// 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.
@@ -11,10 +11,10 @@
#include "base/gfx/rect.h"
#include "base/gfx/size.h"
#include "base/process.h"
+#include "chrome/common/transport_dib.h"
class BackingStore;
class RenderWidgetHost;
-class TransportDIB;
// This class manages backing stores in the browsr. Every RenderWidgetHost is
// associated with a backing store which it requests from this class. The
@@ -30,14 +30,11 @@ class BackingStoreManager {
static BackingStore* GetBackingStore(RenderWidgetHost* host,
const gfx::Size& desired_size);
- // Returns a backing store which is fully ready for consumption, i.e. the
- // bitmap from the renderer has been copied into the backing store dc, or the
- // bitmap in the backing store dc references the renderer bitmap.
+ // Makes a backing store which is fully ready for consumption, i.e. the
+ // bitmap from the renderer has been copied into the backing store.
//
// backing_store_size
// The desired backing store dimensions.
- // process_handle
- // The renderer process handle.
// bitmap_section
// The bitmap section from the renderer.
// bitmap_rect
@@ -45,14 +42,19 @@ class BackingStoreManager {
// needs_full_paint
// Set if we need to send out a request to paint the view
// to the renderer.
- static BackingStore* PrepareBackingStore(
+ // painted_synchronously
+ // Will be set by the function if the request was processed synchronously,
+ // and the bitmap is done being used. False means that the backing store
+ // will paint the bitmap at a later time and that the TransportDIB can't be
+ // freed (it will be the backing store's job to free it later).
+ static void PrepareBackingStore(
RenderWidgetHost* host,
const gfx::Size& backing_store_size,
- base::ProcessHandle process_handle,
- TransportDIB* bitmap,
+ TransportDIB::Id bitmap,
const gfx::Rect& bitmap_rect,
const std::vector<gfx::Rect>& copy_rects,
- bool* needs_full_paint);
+ bool* needs_full_paint,
+ bool* painted_synchronously);
// Returns a matching backing store for the host.
// Returns NULL if we fail to find one.
diff --git a/chrome/browser/renderer_host/backing_store_proxy.cc b/chrome/browser/renderer_host/backing_store_proxy.cc
new file mode 100644
index 0000000..b39eebd
--- /dev/null
+++ b/chrome/browser/renderer_host/backing_store_proxy.cc
@@ -0,0 +1,90 @@
+// 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_proxy.h"
+
+#include "base/gfx/rect.h"
+#include "chrome/browser/gpu_process_host.h"
+#include "chrome/browser/renderer_host/render_process_host.h"
+#include "chrome/browser/renderer_host/render_widget_host.h"
+#include "chrome/common/gpu_messages.h"
+#include "chrome/common/render_messages.h"
+
+BackingStoreProxy::BackingStoreProxy(RenderWidgetHost* widget,
+ const gfx::Size& size,
+ GpuProcessHost* process,
+ int32 routing_id)
+ : BackingStore(widget, size),
+ process_(process),
+ routing_id_(routing_id),
+ waiting_for_paint_ack_(false) {
+ process_->AddRoute(routing_id_, this);
+}
+
+BackingStoreProxy::~BackingStoreProxy() {
+ process_->RemoveRoute(routing_id_);
+}
+
+void BackingStoreProxy::PaintToBackingStore(
+ RenderProcessHost* process,
+ TransportDIB::Id bitmap,
+ const gfx::Rect& bitmap_rect,
+ const std::vector<gfx::Rect>& copy_rects,
+ bool* painted_synchronously) {
+ DCHECK(!waiting_for_paint_ack_);
+
+ if (process_->Send(new GpuMsg_PaintToBackingStore(
+ routing_id_, ::GetProcessId(process->GetHandle()),
+ bitmap, bitmap_rect, copy_rects))) {
+ // Message sent successfully, so the caller can not destroy the
+ // TransportDIB. OnDonePaintingToBackingStore will free it later.
+ *painted_synchronously = false;
+ waiting_for_paint_ack_ = true;
+ } else {
+ // On error, we're done with the TransportDIB and the caller can free it.
+ *painted_synchronously = true;
+ }
+}
+
+bool BackingStoreProxy::CopyFromBackingStore(const gfx::Rect& rect,
+ skia::PlatformCanvas* output) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+void BackingStoreProxy::ScrollBackingStore(int dx, int dy,
+ const gfx::Rect& clip_rect,
+ const gfx::Size& view_size) {
+ process_->Send(new GpuMsg_ScrollBackingStore(routing_id_, dx, dy,
+ clip_rect, view_size));
+}
+
+void BackingStoreProxy::OnMessageReceived(const IPC::Message& msg) {
+ IPC_BEGIN_MESSAGE_MAP(BackingStoreProxy, msg)
+ IPC_MESSAGE_HANDLER(GpuHostMsg_PaintToBackingStore_ACK,
+ OnPaintToBackingStoreACK)
+ IPC_END_MESSAGE_MAP_EX()
+}
+
+void BackingStoreProxy::OnChannelConnected(int32 peer_pid) {
+}
+
+void BackingStoreProxy::OnChannelError() {
+ if (waiting_for_paint_ack_) {
+ // If the GPU process dies while painting, the renderer will be waiting for
+ // the paint ACK before painting any more. Since no ack is coming, we
+ // manually declare that we're done with the transport DIB here so it can
+ // continue.
+ OnPaintToBackingStoreACK();
+ }
+
+ // FIXME(brettw) does this mean we aren't getting any more messages and we
+ // should delete outselves?
+}
+
+void BackingStoreProxy::OnPaintToBackingStoreACK() {
+ DCHECK(waiting_for_paint_ack_);
+ render_widget_host()->DonePaintingToBackingStore();
+ waiting_for_paint_ack_ = false;
+}
diff --git a/chrome/browser/renderer_host/backing_store_proxy.h b/chrome/browser/renderer_host/backing_store_proxy.h
new file mode 100644
index 0000000..f82d948
--- /dev/null
+++ b/chrome/browser/renderer_host/backing_store_proxy.h
@@ -0,0 +1,55 @@
+// 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_PROXY_H_
+#define CHROME_BROWSER_RENDERER_HOST_BACKING_STORE_PROXY_H_
+
+#include "base/basictypes.h"
+#include "chrome/browser/renderer_host/backing_store.h"
+#include "ipc/ipc_channel.h"
+
+#include <windows.h>
+
+class GpuProcessHost;
+
+class BackingStoreProxy : public BackingStore,
+ public IPC::Channel::Listener {
+ public:
+ BackingStoreProxy(RenderWidgetHost* widget, const gfx::Size& size,
+ GpuProcessHost* process, int32 routing_id);
+ virtual ~BackingStoreProxy();
+
+ // BackingStore implementation.
+ virtual void PaintToBackingStore(RenderProcessHost* process,
+ TransportDIB::Id bitmap,
+ const gfx::Rect& bitmap_rect,
+ const std::vector<gfx::Rect>& copy_rects,
+ bool* painted_synchronously);
+ virtual bool CopyFromBackingStore(const gfx::Rect& rect,
+ skia::PlatformCanvas* output);
+ virtual void ScrollBackingStore(int dx, int dy,
+ const gfx::Rect& clip_rect,
+ const gfx::Size& view_size);
+
+ // IPC::Channel::Listener implementation.
+ virtual void OnMessageReceived(const IPC::Message& message);
+ virtual void OnChannelConnected(int32 peer_pid);
+ virtual void OnChannelError();
+
+ private:
+ // Message handlers.
+ void OnPaintToBackingStoreACK();
+
+ GpuProcessHost* process_;
+ int32 routing_id_;
+
+ // Set to true when we're waiting for the GPU process to do a paint and send
+ // back a "done" message. In this case, the renderer will be waiting for our
+ // message that we're done using the backing store.
+ bool waiting_for_paint_ack_;
+
+ DISALLOW_COPY_AND_ASSIGN(BackingStoreProxy);
+};
+
+#endif // CHROME_BROWSER_RENDERER_HOST_BACKING_STORE_PROXY_H_
diff --git a/chrome/browser/renderer_host/backing_store_win.cc b/chrome/browser/renderer_host/backing_store_win.cc
index ae772dc..ede1c40 100644
--- a/chrome/browser/renderer_host/backing_store_win.cc
+++ b/chrome/browser/renderer_host/backing_store_win.cc
@@ -1,14 +1,16 @@
-// 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/browser/renderer_host/backing_store_win.h"
#include "app/gfx/gdi_util.h"
#include "base/command_line.h"
+#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/render_widget_host.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/transport_dib.h"
+#include "skia/ext/platform_canvas.h"
namespace {
@@ -30,7 +32,7 @@ HANDLE CreateDIB(HDC dc, int width, int height, int color_depth) {
hdr.bV5ClrUsed = 0;
hdr.bV5ClrImportant = 0;
- if (BackingStore::ColorManagementEnabled()) {
+ if (BackingStoreWin::ColorManagementEnabled()) {
hdr.bV5CSType = LCS_sRGB;
hdr.bV5Intent = LCS_GM_IMAGES;
}
@@ -67,11 +69,8 @@ void CallStretchDIBits(HDC hdc, int dest_x, int dest_y, int dest_w, int dest_h,
} // namespace
-// BackingStore (Windows) ------------------------------------------------------
-
-BackingStore::BackingStore(RenderWidgetHost* widget, const gfx::Size& size)
- : render_widget_host_(widget),
- size_(size),
+BackingStoreWin::BackingStoreWin(RenderWidgetHost* widget, const gfx::Size& size)
+ : BackingStore(widget, size),
backing_store_dib_(NULL),
original_bitmap_(NULL) {
HDC screen_dc = ::GetDC(NULL);
@@ -85,7 +84,7 @@ BackingStore::BackingStore(RenderWidgetHost* widget, const gfx::Size& size)
ReleaseDC(NULL, screen_dc);
}
-BackingStore::~BackingStore() {
+BackingStoreWin::~BackingStoreWin() {
DCHECK(hdc_);
if (original_bitmap_) {
SelectObject(hdc_, original_bitmap_);
@@ -97,12 +96,8 @@ BackingStore::~BackingStore() {
DeleteDC(hdc_);
}
-size_t BackingStore::MemorySize() {
- return size_.GetArea() * (color_depth_ / 8);
-}
-
// static
-bool BackingStore::ColorManagementEnabled() {
+bool BackingStoreWin::ColorManagementEnabled() {
static bool enabled = false;
static bool checked = false;
if (!checked) {
@@ -113,13 +108,23 @@ bool BackingStore::ColorManagementEnabled() {
return enabled;
}
-void BackingStore::PaintRect(base::ProcessHandle process,
- TransportDIB* bitmap,
- const gfx::Rect& bitmap_rect,
- const gfx::Rect& copy_rect) {
+size_t BackingStoreWin::MemorySize() {
+ return size().GetArea() * (color_depth_ / 8);
+}
+
+void BackingStoreWin::PaintToBackingStore(
+ RenderProcessHost* process,
+ TransportDIB::Id bitmap,
+ const gfx::Rect& bitmap_rect,
+ const std::vector<gfx::Rect>& copy_rects,
+ bool* painted_synchronously) {
+ // Our paints are always synchronous and the TransportDIB can be freed when
+ // we're done (even on error).
+ *painted_synchronously = true;
+
if (!backing_store_dib_) {
- backing_store_dib_ = CreateDIB(hdc_, size_.width(),
- size_.height(), color_depth_);
+ backing_store_dib_ = CreateDIB(hdc_, size().width(),
+ size().height(), color_depth_);
if (!backing_store_dib_) {
NOTREACHED();
return;
@@ -127,28 +132,46 @@ void BackingStore::PaintRect(base::ProcessHandle process,
original_bitmap_ = SelectObject(hdc_, backing_store_dib_);
}
+ TransportDIB* dib = process->GetTransportDIB(bitmap);
+ if (!dib)
+ return;
+
BITMAPINFOHEADER hdr;
gfx::CreateBitmapHeader(bitmap_rect.width(), bitmap_rect.height(), &hdr);
// Account for a bitmap_rect that exceeds the bounds of our view
- gfx::Rect view_rect(0, 0, size_.width(), size_.height());
- gfx::Rect paint_rect = view_rect.Intersect(copy_rect);
-
- CallStretchDIBits(hdc_,
- paint_rect.x(),
- paint_rect.y(),
- paint_rect.width(),
- paint_rect.height(),
- paint_rect.x() - bitmap_rect.x(),
- paint_rect.y() - bitmap_rect.y(),
- paint_rect.width(),
- paint_rect.height(),
- bitmap->memory(),
- reinterpret_cast<BITMAPINFO*>(&hdr));
+ gfx::Rect view_rect(0, 0, size().width(), size().height());
+
+ for (size_t i = 0; i < copy_rects.size(); i++) {
+ gfx::Rect paint_rect = view_rect.Intersect(copy_rects[i]);
+ CallStretchDIBits(hdc_,
+ paint_rect.x(),
+ paint_rect.y(),
+ paint_rect.width(),
+ paint_rect.height(),
+ paint_rect.x() - bitmap_rect.x(),
+ paint_rect.y() - bitmap_rect.y(),
+ paint_rect.width(),
+ paint_rect.height(),
+ dib->memory(),
+ reinterpret_cast<BITMAPINFO*>(&hdr));
+ }
+}
+
+bool BackingStoreWin::CopyFromBackingStore(const gfx::Rect& rect,
+ skia::PlatformCanvas* output) {
+ if (!output->initialize(rect.width(), rect.height(), true))
+ return false;
+
+ HDC temp_dc = output->beginPlatformPaint();
+ BitBlt(temp_dc, 0, 0, rect.width(), rect.height(),
+ hdc(), rect.x(), rect.y(), SRCCOPY);
+ output->endPlatformPaint();
+ return true;
}
-void BackingStore::ScrollRect(int dx, int dy,
- const gfx::Rect& clip_rect,
- const gfx::Size& view_size) {
+void BackingStoreWin::ScrollBackingStore(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/browser/renderer_host/backing_store_win.h b/chrome/browser/renderer_host/backing_store_win.h
new file mode 100644
index 0000000..f280bca
--- /dev/null
+++ b/chrome/browser/renderer_host/backing_store_win.h
@@ -0,0 +1,52 @@
+// 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_WIN_H_
+#define CHROME_BROWSER_RENDERER_HOST_BACKING_STORE_WIN_H_
+
+#include <windows.h>
+
+#include "base/basictypes.h"
+#include "chrome/browser/renderer_host/backing_store.h"
+
+class BackingStoreWin : public BackingStore {
+ public:
+ BackingStoreWin(RenderWidgetHost* widget, const gfx::Size& size);
+ virtual ~BackingStoreWin();
+
+ HDC hdc() { return hdc_; }
+
+ // Returns true if we should convert to the monitor profile when painting.
+ static bool ColorManagementEnabled();
+
+ // BackingStore implementation.
+ virtual size_t MemorySize();
+ virtual void PaintToBackingStore(RenderProcessHost* process,
+ TransportDIB::Id bitmap,
+ const gfx::Rect& bitmap_rect,
+ const std::vector<gfx::Rect>& copy_rects,
+ bool* painted_synchronously);
+ virtual bool CopyFromBackingStore(const gfx::Rect& rect,
+ skia::PlatformCanvas* output);
+ virtual void ScrollBackingStore(int dx, int dy,
+ const gfx::Rect& clip_rect,
+ const gfx::Size& view_size);
+
+ private:
+ // The backing store dc.
+ HDC hdc_;
+
+ // Handle to the backing store dib.
+ HANDLE backing_store_dib_;
+
+ // Handle to the original bitmap in the dc.
+ HANDLE original_bitmap_;
+
+ // Number of bits per pixel of the screen.
+ int color_depth_;
+
+ DISALLOW_COPY_AND_ASSIGN(BackingStoreWin);
+};
+
+#endif // CHROME_BROWSER_RENDERER_HOST_BACKING_STORE_WIN_H_
diff --git a/chrome/browser/renderer_host/backing_store_x.cc b/chrome/browser/renderer_host/backing_store_x.cc
index 1cf4620..af334fa 100644
--- a/chrome/browser/renderer_host/backing_store_x.cc
+++ b/chrome/browser/renderer_host/backing_store_x.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2006-2008 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/browser/renderer_host/backing_store_x.h"
#include <stdlib.h>
#include <sys/ipc.h>
@@ -16,12 +16,15 @@
#include <utility>
#include "base/compiler_specific.h"
+#include "base/gfx/rect.h"
#include "base/histogram.h"
#include "base/logging.h"
#include "base/time.h"
+#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/common/transport_dib.h"
#include "chrome/common/x11_util.h"
#include "chrome/common/x11_util_internal.h"
+#include "skia/ext/platform_canvas.h"
#include "third_party/skia/include/core/SkBitmap.h"
// X Backing Stores:
@@ -45,12 +48,11 @@ static void DestroySharedImage(Display* display,
shmdt(shminfo->shmaddr);
}
-BackingStore::BackingStore(RenderWidgetHost* widget,
- const gfx::Size& size,
- void* visual,
- int depth)
- : render_widget_host_(widget),
- size_(size),
+BackingStoreX::BackingStoreX(RenderWidgetHost* widget,
+ const gfx::Size& size,
+ void* visual,
+ int depth)
+ : BackingStore(widget, size),
display_(x11_util::GetXDisplay()),
shared_memory_support_(x11_util::QuerySharedMemorySupport(display_)),
use_render_(x11_util::QueryRenderSupport(display_)),
@@ -76,9 +78,8 @@ BackingStore::BackingStore(RenderWidgetHost* widget,
pixmap_gc_ = XCreateGC(display_, pixmap_, 0, NULL);
}
-BackingStore::BackingStore(RenderWidgetHost* widget, const gfx::Size& size)
- : render_widget_host_(widget),
- size_(size),
+BackingStoreX::BackingStoreX(RenderWidgetHost* widget, const gfx::Size& size)
+ : BackingStore(widget, size),
display_(NULL),
shared_memory_support_(x11_util::SHARED_MEMORY_NONE),
use_render_(false),
@@ -87,7 +88,7 @@ BackingStore::BackingStore(RenderWidgetHost* widget, const gfx::Size& size)
root_window_(0) {
}
-BackingStore::~BackingStore() {
+BackingStoreX::~BackingStoreX() {
// In unit tests, display_ may be NULL.
if (!display_)
return;
@@ -97,16 +98,17 @@ BackingStore::~BackingStore() {
XFreeGC(display_, static_cast<GC>(pixmap_gc_));
}
-size_t BackingStore::MemorySize() {
+size_t BackingStoreX::MemorySize() {
if (!use_render_)
- return size_.GetArea() * (pixmap_bpp_ / 8);
+ return size().GetArea() * (pixmap_bpp_ / 8);
else
- return size_.GetArea() * 4;
+ return size().GetArea() * 4;
}
-void BackingStore::PaintRectWithoutXrender(TransportDIB* bitmap,
- const gfx::Rect& bitmap_rect,
- const gfx::Rect& copy_rect) {
+void BackingStoreX::PaintRectWithoutXrender(
+ TransportDIB* bitmap,
+ const gfx::Rect& bitmap_rect,
+ const std::vector<gfx::Rect>& copy_rects) {
const int width = bitmap_rect.width();
const int height = bitmap_rect.height();
Pixmap pixmap = XCreatePixmap(display_, root_window_, width, height,
@@ -203,28 +205,37 @@ void BackingStore::PaintRectWithoutXrender(TransportDIB* bitmap,
<< " bpp:" << pixmap_bpp_ << ")";
}
- XCopyArea(display_,
- pixmap, // src
- pixmap_, // dest
- static_cast<GC>(pixmap_gc_), // gc
- copy_rect.x() - bitmap_rect.x(), // src_x
- copy_rect.y() - bitmap_rect.y(), // src_y
- copy_rect.width(), // width
- copy_rect.height(), // height
- copy_rect.x(), // dest_x
- copy_rect.y()); // dest_y
+ for (size_t i = 0; i < copy_rects.size(); i++) {
+ const gfx::Rect& copy_rect = copy_rects[i];
+ XCopyArea(display_,
+ pixmap, // src
+ pixmap_, // dest
+ static_cast<GC>(pixmap_gc_), // gc
+ copy_rect.x() - bitmap_rect.x(), // src_x
+ copy_rect.y() - bitmap_rect.y(), // src_y
+ copy_rect.width(), // width
+ copy_rect.height(), // height
+ copy_rect.x(), // dest_x
+ copy_rect.y()); // dest_y
+ }
XFreePixmap(display_, pixmap);
}
-void BackingStore::PaintRect(base::ProcessHandle process,
- TransportDIB* bitmap,
- const gfx::Rect& bitmap_rect,
- const gfx::Rect& copy_rect) {
+void BackingStoreX::PaintToBackingStore(
+ RenderProcessHost* process,
+ TransportDIB::Id bitmap,
+ const gfx::Rect& bitmap_rect,
+ const std::vector<gfx::Rect>& copy_rects,
+ bool* painted_synchronously) {
+ // Our paints are always synchronous and the caller can free the TransportDIB
+ // when we're done, even on error.
+ *painted_synchronously = true;
+
if (!display_)
return;
- if (bitmap_rect.IsEmpty() || copy_rect.IsEmpty())
+ if (bitmap_rect.IsEmpty())
return;
const int width = bitmap_rect.width();
@@ -235,15 +246,19 @@ void BackingStore::PaintRect(base::ProcessHandle process,
if (width > 23170 || height > 23170)
return;
+ TransportDIB* dib = process->GetTransportDIB(bitmap);
+ if (!dib)
+ return;
+
if (!use_render_)
- return PaintRectWithoutXrender(bitmap, bitmap_rect, copy_rect);
+ return PaintRectWithoutXrender(dib, bitmap_rect, copy_rects);
Picture picture;
Pixmap pixmap;
if (shared_memory_support_ == x11_util::SHARED_MEMORY_PIXMAP) {
XShmSegmentInfo shminfo = {0};
- shminfo.shmseg = bitmap->MapToX(display_);
+ shminfo.shmseg = dib->MapToX(display_);
// The NULL in the following is the |data| pointer: this is an artifact of
// Xlib trying to be helpful, rather than just exposing the X protocol. It
@@ -261,12 +276,12 @@ void BackingStore::PaintRect(base::ProcessHandle process,
GC gc = XCreateGC(display_, pixmap, 0, NULL);
if (shared_memory_support_ == x11_util::SHARED_MEMORY_PUTIMAGE) {
- const XID shmseg = bitmap->MapToX(display_);
+ const XID shmseg = dib->MapToX(display_);
XShmSegmentInfo shminfo;
memset(&shminfo, 0, sizeof(shminfo));
shminfo.shmseg = shmseg;
- shminfo.shmaddr = static_cast<char*>(bitmap->memory());
+ shminfo.shmaddr = static_cast<char*>(dib->memory());
// TODO(evanm): verify that Xlib isn't doing any conversions here.
XImage* image = XShmCreateImage(display_, static_cast<Visual*>(visual_),
@@ -298,7 +313,7 @@ void BackingStore::PaintRect(base::ProcessHandle process,
image.red_mask = 0xff;
image.green_mask = 0xff00;
image.blue_mask = 0xff0000;
- image.data = static_cast<char*>(bitmap->memory());
+ image.data = static_cast<char*>(dib->memory());
XPutImage(display_, pixmap, gc, &image,
0, 0 /* source x, y */, 0, 0 /* dest x, y */,
@@ -308,19 +323,23 @@ void BackingStore::PaintRect(base::ProcessHandle process,
}
picture = x11_util::CreatePictureFromSkiaPixmap(display_, pixmap);
- XRenderComposite(display_,
- PictOpSrc, // op
- picture, // src
- 0, // mask
- picture_, // dest
- copy_rect.x() - bitmap_rect.x(), // src_x
- copy_rect.y() - bitmap_rect.y(), // src_y
- 0, // mask_x
- 0, // mask_y
- copy_rect.x(), // dest_x
- copy_rect.y(), // dest_y
- copy_rect.width(), // width
- copy_rect.height()); // height
+
+ for (size_t i = 0; i < copy_rects.size(); i++) {
+ const gfx::Rect& copy_rect = copy_rects[i];
+ XRenderComposite(display_,
+ PictOpSrc, // op
+ picture, // src
+ 0, // mask
+ picture_, // dest
+ copy_rect.x() - bitmap_rect.x(), // src_x
+ copy_rect.y() - bitmap_rect.y(), // src_y
+ 0, // mask_x
+ 0, // mask_y
+ copy_rect.x(), // dest_x
+ copy_rect.y(), // dest_y
+ copy_rect.width(), // width
+ copy_rect.height()); // height
+ }
// In the case of shared memory, we wait for the composite to complete so that
// we are sure that the X server has finished reading from the shared memory
@@ -332,9 +351,83 @@ void BackingStore::PaintRect(base::ProcessHandle process,
XFreePixmap(display_, pixmap);
}
-void BackingStore::ScrollRect(int dx, int dy,
- const gfx::Rect& clip_rect,
- const gfx::Size& view_size) {
+bool BackingStoreX::CopyFromBackingStore(const gfx::Rect& rect,
+ skia::PlatformCanvas* output) {
+ base::TimeTicks begin_time = base::TimeTicks::Now();
+ const int width = std::min(size().width(), rect.width());
+ const int height = std::min(size().height(), rect.height());
+
+ XImage* image;
+ XShmSegmentInfo shminfo; // Used only when shared memory is enabled.
+ if (shared_memory_support_ != x11_util::SHARED_MEMORY_NONE) {
+ // Use shared memory for faster copies when it's available.
+ Visual* visual = static_cast<Visual*>(visual_);
+ memset(&shminfo, 0, sizeof(shminfo));
+ image = XShmCreateImage(display_, visual, 32,
+ ZPixmap, NULL, &shminfo, width, height);
+
+ // Create the shared memory segment for the image and map it.
+ shminfo.shmid = shmget(IPC_PRIVATE, image->bytes_per_line * image->height,
+ IPC_CREAT|0666);
+ if (shminfo.shmid == -1) {
+ XDestroyImage(image);
+ return false;
+ }
+
+ void* mapped_memory = shmat(shminfo.shmid, NULL, SHM_RDONLY);
+ shmctl(shminfo.shmid, IPC_RMID, 0);
+ if (mapped_memory == (void*)-1) {
+ XDestroyImage(image);
+ return false;
+ }
+ shminfo.shmaddr = image->data = static_cast<char*>(mapped_memory);
+
+ if (!XShmAttach(display_, &shminfo) ||
+ !XShmGetImage(display_, pixmap_, image, rect.x(), rect.y(),
+ AllPlanes)) {
+ DestroySharedImage(display_, image, &shminfo);
+ return false;
+ }
+ } else {
+ // Non-shared memory case just copy the image from the server.
+ image = XGetImage(display_, pixmap_,
+ rect.x(), rect.y(), width, height,
+ AllPlanes, ZPixmap);
+ }
+
+ // TODO(jhawkins): Need to convert the image data if the image bits per pixel
+ // is not 32.
+ if (!output->initialize(width, height, true) ||
+ image->bits_per_pixel != 32) {
+ if (shared_memory_support_ != x11_util::SHARED_MEMORY_NONE)
+ DestroySharedImage(display_, image, &shminfo);
+ else
+ XDestroyImage(image);
+ return false;
+ }
+
+ // The X image might have a different row stride, so iterate through it and
+ // copy each row out, only up to the pixels we're actually using.
+ SkBitmap bitmap = output->getTopPlatformDevice().accessBitmap(true);
+ for (int y = 0; y < height; y++) {
+ uint32* dest_row = bitmap.getAddr32(0, y);
+ const char* src_row = &image->data[image->bytes_per_line * y];
+ memcpy(dest_row, src_row, width * 4);
+ }
+
+ if (shared_memory_support_ != x11_util::SHARED_MEMORY_NONE)
+ DestroySharedImage(display_, image, &shminfo);
+ else
+ XDestroyImage(image);
+
+ HISTOGRAM_TIMES("BackingStore.RetrievalFromX",
+ base::TimeTicks::Now() - begin_time);
+ return true;
+}
+
+void BackingStoreX::ScrollBackingStore(int dx, int dy,
+ const gfx::Rect& clip_rect,
+ const gfx::Size& view_size) {
if (!display_)
return;
@@ -366,22 +459,22 @@ void BackingStore::ScrollRect(int dx, int dy,
}
}
-void BackingStore::ShowRect(const gfx::Rect& rect, XID target) {
+void BackingStoreX::ShowRect(const gfx::Rect& rect, XID target) {
XCopyArea(display_, pixmap_, target, static_cast<GC>(pixmap_gc_),
rect.x(), rect.y(), rect.width(), rect.height(),
rect.x(), rect.y());
}
#if defined(TOOLKIT_GTK)
-void BackingStore::PaintToRect(const gfx::Rect& rect, GdkDrawable* target) {
+void BackingStoreX::PaintToRect(const gfx::Rect& rect, GdkDrawable* target) {
cairo_surface_t* surface = cairo_xlib_surface_create(
display_, pixmap_, static_cast<Visual*>(visual_),
- size_.width(), size_.height());
+ size().width(), size().height());
cairo_t* cr = gdk_cairo_create(target);
cairo_translate(cr, rect.x(), rect.y());
- double x_scale = static_cast<double>(rect.width()) / size_.width();
- double y_scale = static_cast<double>(rect.height()) / size_.height();
+ double x_scale = static_cast<double>(rect.width()) / size().width();
+ double y_scale = static_cast<double>(rect.height()) / size().height();
cairo_scale(cr, x_scale, y_scale);
cairo_pattern_t* pattern = cairo_pattern_create_for_surface(surface);
@@ -396,76 +489,3 @@ void BackingStore::PaintToRect(const gfx::Rect& rect, GdkDrawable* target) {
cairo_destroy(cr);
}
#endif
-
-SkBitmap BackingStore::PaintRectToBitmap(const gfx::Rect& rect) {
- base::TimeTicks begin_time = base::TimeTicks::Now();
- const int width = std::min(size_.width(), rect.width());
- const int height = std::min(size_.height(), rect.height());
-
- XImage* image;
- XShmSegmentInfo shminfo; // Used only when shared memory is enabled.
- if (shared_memory_support_ != x11_util::SHARED_MEMORY_NONE) {
- // Use shared memory for faster copies when it's available.
- Visual* visual = static_cast<Visual*>(visual_);
- memset(&shminfo, 0, sizeof(shminfo));
- image = XShmCreateImage(display_, visual, 32,
- ZPixmap, NULL, &shminfo, width, height);
-
- // Create the shared memory segment for the image and map it.
- shminfo.shmid = shmget(IPC_PRIVATE, image->bytes_per_line * image->height,
- IPC_CREAT|0666);
- if (shminfo.shmid == -1) {
- XDestroyImage(image);
- return SkBitmap();
- }
-
- void* mapped_memory = shmat(shminfo.shmid, NULL, SHM_RDONLY);
- shmctl(shminfo.shmid, IPC_RMID, 0);
- if (mapped_memory == (void*)-1) {
- XDestroyImage(image);
- return SkBitmap();
- }
- shminfo.shmaddr = image->data = static_cast<char*>(mapped_memory);
-
- if (!XShmAttach(display_, &shminfo) ||
- !XShmGetImage(display_, pixmap_, image, rect.x(), rect.y(),
- AllPlanes)) {
- DestroySharedImage(display_, image, &shminfo);
- return SkBitmap();
- }
- } else {
- // Non-shared memory case just copy the image from the server.
- image = XGetImage(display_, pixmap_,
- rect.x(), rect.y(), width, height,
- AllPlanes, ZPixmap);
- }
-
- // TODO(jhawkins): Need to convert the image data if the image bits per pixel
- // is not 32.
- if (image->bits_per_pixel != 32) {
- if (shared_memory_support_ != x11_util::SHARED_MEMORY_NONE)
- DestroySharedImage(display_, image, &shminfo);
- else
- XDestroyImage(image);
- return SkBitmap();
- }
-
- // Create a bitmap to put the results into, being careful to use the stride
- // from the image rather than the width for the size.
- SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height,
- image->bytes_per_line);
- bitmap.allocPixels();
- unsigned char* bitmap_data =
- reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0));
- memcpy(bitmap_data, image->data, image->bytes_per_line * height);
-
- if (shared_memory_support_ != x11_util::SHARED_MEMORY_NONE)
- DestroySharedImage(display_, image, &shminfo);
- else
- XDestroyImage(image);
-
- HISTOGRAM_TIMES("BackingStore.RetrievalFromX",
- base::TimeTicks::Now() - begin_time);
- return bitmap;
-}
diff --git a/chrome/browser/renderer_host/backing_store_x.h b/chrome/browser/renderer_host/backing_store_x.h
new file mode 100644
index 0000000..39c5fe9
--- /dev/null
+++ b/chrome/browser/renderer_host/backing_store_x.h
@@ -0,0 +1,92 @@
+// 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_X_H_
+#define CHROME_BROWSER_RENDERER_HOST_BACKING_STORE_X_H_
+
+#include "base/basictypes.h"
+#include "build/build_config.h"
+#include "chrome/browser/renderer_host/backing_store.h"
+#include "chrome/common/x11_util.h"
+
+typedef struct _GdkDrawable GdkDrawable;
+class SkBitmap;
+
+class BackingStoreX : 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.
+ BackingStoreX(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
+ BackingStoreX(RenderWidgetHost* widget, const gfx::Size& size);
+
+ virtual ~BackingStoreX();
+
+ 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);
+
+#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 PaintToBackingStore(
+ RenderProcessHost* process,
+ TransportDIB::Id bitmap,
+ const gfx::Rect& bitmap_rect,
+ const std::vector<gfx::Rect>& copy_rects,
+ bool* painted_synchronously);
+ virtual bool CopyFromBackingStore(const gfx::Rect& rect,
+ skia::PlatformCanvas* output);
+ virtual void ScrollBackingStore(int dx, int dy,
+ const gfx::Rect& clip_rect,
+ const gfx::Size& view_size);
+
+ private:
+ // Paints the bitmap from the renderer onto the backing store without
+ // using Xrender to composite the pixmaps.
+ void PaintRectWithoutXrender(TransportDIB* bitmap,
+ const gfx::Rect& bitmap_rect,
+ const std::vector<gfx::Rect>& copy_rects);
+
+ // This is the connection to the X server where this backing store will be
+ // displayed.
+ Display* const display_;
+ // What flavor, if any, MIT-SHM (X shared memory) support we have.
+ const x11_util::SharedMemorySupport shared_memory_support_;
+ // If this is true, then we can use Xrender to composite our pixmaps.
+ const bool use_render_;
+ // If |use_render_| is false, this is the number of bits-per-pixel for |depth|
+ int pixmap_bpp_;
+ // if |use_render_| is false, we need the Visual to get the RGB masks.
+ void* const visual_;
+ // This is the depth of the target window.
+ const int visual_depth_;
+ // The parent window (probably a GtkDrawingArea) for this backing store.
+ const XID root_window_;
+ // This is a handle to the server side pixmap which is our backing store.
+ XID pixmap_;
+ // This is the RENDER picture pointing at |pixmap_|.
+ XID picture_;
+ // This is a default graphic context, used in XCopyArea
+ void* pixmap_gc_;
+
+ DISALLOW_COPY_AND_ASSIGN(BackingStoreX);
+};
+
+#endif // CHROME_BROWSER_RENDERER_HOST_BACKING_STORE_X_H_
diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc
index eac566b..32c141c 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.cc
+++ b/chrome/browser/renderer_host/browser_render_process_host.cc
@@ -735,7 +735,7 @@ bool BrowserRenderProcessHost::Send(IPC::Message* msg) {
void BrowserRenderProcessHost::OnMessageReceived(const IPC::Message& msg) {
mark_child_process_activity_time();
if (msg.routing_id() == MSG_ROUTING_CONTROL) {
- // dispatch control messages
+ // Dispatch control messages.
bool msg_is_ok = true;
IPC_BEGIN_MESSAGE_MAP_EX(BrowserRenderProcessHost, msg, msg_is_ok)
IPC_MESSAGE_HANDLER(ViewHostMsg_PageContents, OnPageContents)
@@ -762,7 +762,7 @@ void BrowserRenderProcessHost::OnMessageReceived(const IPC::Message& msg) {
return;
}
- // dispatch incoming messages to the appropriate TabContents
+ // Dispatch incoming messages to the appropriate RenderView/WidgetHost.
IPC::Channel::Listener* listener = GetListenerByID(msg.routing_id());
if (!listener) {
if (msg.is_sync()) {
diff --git a/chrome/browser/renderer_host/gpu_view_host_win.cc b/chrome/browser/renderer_host/gpu_view_host_win.cc
new file mode 100644
index 0000000..52fae31
--- /dev/null
+++ b/chrome/browser/renderer_host/gpu_view_host_win.cc
@@ -0,0 +1,36 @@
+// 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/gpu_view_host_win.h"
+
+#include "chrome/browser/gpu_process_host.h"
+#include "chrome/browser/renderer_host/backing_store_proxy.h"
+#include "chrome/common/gpu_messages.h"
+
+GpuViewHostWin::GpuViewHostWin(RenderWidgetHostViewWin* view,
+ HWND parent)
+ : view_(view),
+ process_(GpuProcessHost::Get()),
+ routing_id_(0) {
+ if (!process_) {
+ // TODO(brettw) handle error.
+ return;
+ }
+ routing_id_ = process_->NewRenderWidgetHostView(
+ gfx::IdFromNativeView(parent));
+}
+
+GpuViewHostWin::~GpuViewHostWin() {
+}
+
+BackingStore* GpuViewHostWin::CreateBackingStore(
+ RenderWidgetHost* widget,
+ const gfx::Size& size) {
+ int32 backing_store_routing_id = process_->GetNextRoutingId();
+ process_->Send(new GpuMsg_NewBackingStore(routing_id_,
+ backing_store_routing_id,
+ size));
+ return new BackingStoreProxy(widget, size,
+ process_, backing_store_routing_id);
+}
diff --git a/chrome/browser/renderer_host/gpu_view_host_win.h b/chrome/browser/renderer_host/gpu_view_host_win.h
new file mode 100644
index 0000000..a995fa0
--- /dev/null
+++ b/chrome/browser/renderer_host/gpu_view_host_win.h
@@ -0,0 +1,39 @@
+// 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_GPU_VIEW_HOST_WIN_H_
+#define CHROME_BROWSER_RENDERER_HOST_GPU_VIEW_HOST_WIN_H_
+
+#include <windows.h>
+
+#include "base/basictypes.h"
+
+class BackingStore;
+class GpuProcessHost;
+class RenderWidgetHost;
+class RenderWidgetHostViewWin;
+
+namespace gfx {
+class Size;
+}
+
+// A proxy for the GPU process' window for rendering pages.
+class GpuViewHostWin {
+ public:
+ GpuViewHostWin(RenderWidgetHostViewWin* view, HWND parent);
+ ~GpuViewHostWin();
+
+ BackingStore* CreateBackingStore(RenderWidgetHost* widget,
+ const gfx::Size& size);
+
+ private:
+ RenderWidgetHostViewWin* view_;
+
+ GpuProcessHost* process_;
+ int32 routing_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuViewHostWin);
+};
+
+#endif // CHROME_BROWSER_RENDERER_HOST_GPU_VIEW_HOST_WIN_H_
diff --git a/chrome/browser/renderer_host/render_process_host.h b/chrome/browser/renderer_host/render_process_host.h
index 7979d24..9d4855c 100644
--- a/chrome/browser/renderer_host/render_process_host.h
+++ b/chrome/browser/renderer_host/render_process_host.h
@@ -208,8 +208,10 @@ class RenderProcessHost : public IPC::Channel::Sender,
// Returns the process object associated with the child process. In certain
// tests or single-process mode, this will actually represent the current
// process.
- // NOTE: this is not valid after calling Init, as it starts the process
- // asynchronously. It's guaranteed to be valid after the first IPC arrives.
+ //
+ // NOTE: this is not necessarily valid immediately after calling Init, as
+ // Init starts the process asynchronously. It's guaranteed to be valid after
+ // the first IPC arrives.
virtual base::ProcessHandle GetHandle() = 0;
// Transport DIB functions ---------------------------------------------------
diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc
index ad94aa6..4798516 100644
--- a/chrome/browser/renderer_host/render_widget_host.cc
+++ b/chrome/browser/renderer_host/render_widget_host.cc
@@ -1,4 +1,4 @@
-// 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.
@@ -314,6 +314,10 @@ BackingStore* RenderWidgetHost::AllocBackingStore(const gfx::Size& size) {
return view_->AllocBackingStore(size);
}
+void RenderWidgetHost::DonePaintingToBackingStore() {
+ Send(new ViewMsg_UpdateRect_ACK(routing_id()));
+}
+
void RenderWidgetHost::StartHangMonitorTimeout(TimeDelta delay) {
time_when_considered_hung_ = Time::Now() + delay;
@@ -649,6 +653,7 @@ void RenderWidgetHost::OnMsgUpdateRect(
const size_t size = params.bitmap_rect.height() *
params.bitmap_rect.width() * 4;
TransportDIB* dib = process_->GetTransportDIB(params.bitmap);
+ bool painted_synchronously = true; // Default to sending a paint ACK below.
if (dib) {
if (dib->size() < size) {
DLOG(WARNING) << "Transport DIB too small for given rectangle";
@@ -664,16 +669,19 @@ void RenderWidgetHost::OnMsgUpdateRect(
// Paint the backing store. This will update it with the renderer-supplied
// bits. The view will read out of the backing store later to actually
// draw to the screen.
- PaintBackingStoreRect(dib, params.bitmap_rect, params.copy_rects,
- params.view_size);
+ PaintBackingStoreRect(params.bitmap, params.bitmap_rect,
+ params.copy_rects, params.view_size,
+ &painted_synchronously);
}
}
// ACK early so we can prefetch the next PaintRect if there is a next one.
// This must be done AFTER we're done painting with the bitmap supplied by the
// renderer. This ACK is a signal to the renderer that the backing store can
- // be re-used, so the bitmap may be invalid after this call.
- Send(new ViewMsg_UpdateRect_ACK(routing_id_));
+ // be re-used, so the bitmap may be invalid after this call. If the backing
+ // store is painting asynchronously, it will manage issuing this IPC.
+ if (painted_synchronously)
+ Send(new ViewMsg_UpdateRect_ACK(routing_id_));
// We don't need to update the view if the view is hidden. We must do this
// early return after the ACK is sent, however, or the renderer will not send
@@ -825,10 +833,15 @@ void RenderWidgetHost::OnMsgGetRootWindowRect(gfx::NativeViewId window_id,
#endif
void RenderWidgetHost::PaintBackingStoreRect(
- TransportDIB* bitmap,
+ TransportDIB::Id bitmap,
const gfx::Rect& bitmap_rect,
const std::vector<gfx::Rect>& copy_rects,
- const gfx::Size& view_size) {
+ const gfx::Size& view_size,
+ bool* painted_synchronously) {
+ // On failure, we need to be sure our caller knows we're done with the
+ // backing store.
+ *painted_synchronously = true;
+
// The view may be destroyed already.
if (!view_)
return;
@@ -842,10 +855,9 @@ void RenderWidgetHost::PaintBackingStoreRect(
}
bool needs_full_paint = false;
- BackingStoreManager::PrepareBackingStore(this, view_size,
- process_->GetHandle(),
- bitmap, bitmap_rect, copy_rects,
- &needs_full_paint);
+ BackingStoreManager::PrepareBackingStore(this, view_size, bitmap, bitmap_rect,
+ copy_rects, &needs_full_paint,
+ painted_synchronously);
if (needs_full_paint) {
repaint_start_time_ = TimeTicks::Now();
repaint_ack_pending_ = true;
@@ -870,7 +882,7 @@ void RenderWidgetHost::ScrollBackingStoreRect(int dx, int dy,
BackingStore* backing_store = BackingStoreManager::Lookup(this);
if (!backing_store || (backing_store->size() != view_size))
return;
- backing_store->ScrollRect(dx, dy, clip_rect, view_size);
+ backing_store->ScrollBackingStore(dx, dy, clip_rect, view_size);
}
void RenderWidgetHost::ToggleSpellPanel(bool is_currently_visible) {
diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h
index d59fc4e..ddda002 100644
--- a/chrome/browser/renderer_host/render_widget_host.h
+++ b/chrome/browser/renderer_host/render_widget_host.h
@@ -16,6 +16,7 @@
#include "chrome/common/edit_command.h"
#include "chrome/common/native_web_keyboard_event.h"
#include "chrome/common/property_bag.h"
+#include "chrome/common/transport_dib.h"
#include "ipc/ipc_channel.h"
#include "testing/gtest/include/gtest/gtest_prod.h"
#include "third_party/WebKit/WebKit/chromium/public/WebTextDirection.h"
@@ -214,6 +215,11 @@ class RenderWidgetHost : public IPC::Channel::Listener,
// (for example, if we don't currently have a RenderWidgetHostView.)
BackingStore* AllocBackingStore(const gfx::Size& size);
+ // When a backing store does asynchronous painting, it will call this function
+ // when it is done with the DIB. We will then forward a message to the
+ // renderer to send another paint.
+ void DonePaintingToBackingStore();
+
// Checks to see if we can give up focus to this widget through a JS call.
virtual bool CanBlur() const { return true; }
@@ -434,10 +440,15 @@ class RenderWidgetHost : public IPC::Channel::Listener,
#endif
// Paints the given bitmap to the current backing store at the given location.
- void PaintBackingStoreRect(TransportDIB* dib,
+ // |*painted_synchronously| will be true if the message was processed
+ // synchronously, and the bitmap is done being used. False means that the
+ // backing store will paint the bitmap at a later time and that the DIB can't
+ // be freed (it will be the backing store's job to free it later).
+ void PaintBackingStoreRect(TransportDIB::Id bitmap,
const gfx::Rect& bitmap_rect,
const std::vector<gfx::Rect>& copy_rects,
- const gfx::Size& view_size);
+ const gfx::Size& view_size,
+ bool* painted_synchronously);
// Scrolls the given |clip_rect| in the backing by the given dx/dy amount. The
// |dib| and its corresponding location |bitmap_rect| in the backing store
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 aee6b5f..6291574 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 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.
@@ -28,7 +28,7 @@
#include "chrome/common/gtk_util.h"
#include "chrome/common/native_web_keyboard_event.h"
#include "chrome/common/x11_util.h"
-#include "chrome/browser/renderer_host/backing_store.h"
+#include "chrome/browser/renderer_host/backing_store_x.h"
#include "chrome/browser/renderer_host/gtk_im_context_wrapper.h"
#include "chrome/browser/renderer_host/gtk_key_bindings_handler.h"
#include "chrome/browser/renderer_host/render_widget_host.h"
@@ -528,7 +528,8 @@ void RenderWidgetHostViewGtk::DidScrollBackingStoreRect(const gfx::Rect& rect,
return;
// TODO(darin): Implement the equivalent of Win32's ScrollWindowEX. Can that
- // be done using XCopyArea? Perhaps similar to BackingStore::ScrollRect?
+ // be done using XCopyArea? Perhaps similar to
+ // BackingStore::ScrollBackingStore?
if (about_to_validate_and_paint_)
invalid_rect_ = invalid_rect_.Union(rect);
else
@@ -596,9 +597,9 @@ void RenderWidgetHostViewGtk::ShowingContextMenu(bool showing) {
BackingStore* RenderWidgetHostViewGtk::AllocBackingStore(
const gfx::Size& size) {
- return new BackingStore(host_, size,
- x11_util::GetVisualFromGtkWidget(view_.get()),
- gtk_widget_get_visual(view_.get())->depth);
+ return new BackingStoreX(host_, size,
+ x11_util::GetVisualFromGtkWidget(view_.get()),
+ gtk_widget_get_visual(view_.get())->depth);
}
void RenderWidgetHostViewGtk::SetBackground(const SkBitmap& background) {
@@ -611,7 +612,8 @@ void RenderWidgetHostViewGtk::Paint(const gfx::Rect& damage_rect) {
invalid_rect_ = damage_rect;
about_to_validate_and_paint_ = true;
- BackingStore* backing_store = host_->GetBackingStore(true);
+ BackingStoreX* backing_store = static_cast<BackingStoreX*>(
+ host_->GetBackingStore(true));
// Calling GetBackingStore maybe have changed |invalid_rect_|...
about_to_validate_and_paint_ = false;
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.mm b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
index 55cfaef..5f45aec 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
@@ -11,7 +11,7 @@
#include "chrome/browser/browser_trial.h"
#import "chrome/browser/cocoa/rwhvm_editcommand_helper.h"
#include "chrome/browser/plugin_process_host.h"
-#include "chrome/browser/renderer_host/backing_store.h"
+#include "chrome/browser/renderer_host/backing_store_mac.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/render_widget_host.h"
#include "chrome/browser/spellchecker_platform_engine.h"
@@ -383,7 +383,7 @@ void RenderWidgetHostViewMac::SetTooltipText(const std::wstring& tooltip_text) {
BackingStore* RenderWidgetHostViewMac::AllocBackingStore(
const gfx::Size& size) {
- return new BackingStore(render_widget_host_, size);
+ return new BackingStoreMac(render_widget_host_, size);
}
// Display a popup menu for WebKit using Cocoa widgets.
@@ -758,8 +758,8 @@ void RenderWidgetHostViewMac::SetBackground(const SkBitmap& background) {
renderWidgetHostView_->invalid_rect_ = dirtyRect;
renderWidgetHostView_->about_to_validate_and_paint_ = true;
- BackingStore* backing_store =
- renderWidgetHostView_->render_widget_host_->GetBackingStore(true);
+ BackingStoreMac* backing_store = static_cast<BackingStoreMac*>(
+ renderWidgetHostView_->render_widget_host_->GetBackingStore(true));
renderWidgetHostView_->about_to_validate_and_paint_ = false;
dirtyRect = renderWidgetHostView_->invalid_rect_;
diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.cc b/chrome/browser/renderer_host/render_widget_host_view_win.cc
index 8be4df5..d6287ac 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_win.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_win.cc
@@ -1,4 +1,4 @@
-// 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.
@@ -21,6 +21,8 @@
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/plugin_process_host.h"
#include "chrome/browser/renderer_host/backing_store.h"
+#include "chrome/browser/renderer_host/backing_store_win.h"
+#include "chrome/browser/renderer_host/gpu_view_host_win.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/render_widget_host.h"
#include "chrome/common/chrome_constants.h"
@@ -259,6 +261,13 @@ RenderWidgetHostViewWin::~RenderWidgetHostViewWin() {
ResetTooltip();
}
+void RenderWidgetHostViewWin::CreateWnd(HWND parent) {
+ Create(parent); // ATL function to create the window.
+ // Uncommenting this will enable experimental out-of-process painting.
+ // Contact brettw for more,
+ // gpu_view_host_.reset(new GpuViewHostWin(this, m_hWnd));
+}
+
///////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostViewWin, RenderWidgetHostView implementation:
@@ -702,7 +711,9 @@ void RenderWidgetHostViewWin::SetTooltipText(const std::wstring& tooltip_text) {
BackingStore* RenderWidgetHostViewWin::AllocBackingStore(
const gfx::Size& size) {
- return new BackingStore(render_widget_host_, size);
+ if (gpu_view_host_.get())
+ return gpu_view_host_->CreateBackingStore(render_widget_host_, size);
+ return new BackingStoreWin(render_widget_host_, size);
}
void RenderWidgetHostViewWin::SetBackground(const SkBitmap& background) {
@@ -758,11 +769,22 @@ void RenderWidgetHostViewWin::OnDestroy() {
TrackMouseLeave(false);
}
-void RenderWidgetHostViewWin::OnPaint(HDC dc) {
+void RenderWidgetHostViewWin::OnPaint(HDC unused_dc) {
DCHECK(render_widget_host_->process()->HasConnection());
+ if (gpu_view_host_.get()) {
+ // 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.
+ CPaintDC paint_dc(m_hWnd);
+ FillRect(paint_dc.m_hDC, &paint_dc.m_ps.rcPaint,
+ static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)));
+ return;
+ }
+
about_to_validate_and_paint_ = true;
- BackingStore* backing_store = render_widget_host_->GetBackingStore(true);
+ BackingStoreWin* backing_store = static_cast<BackingStoreWin*>(
+ render_widget_host_->GetBackingStore(true));
// We initialize |paint_dc| (and thus call BeginPaint()) after calling
// GetBackingStore(), so that if it updates the invalid rect we'll catch the
@@ -783,7 +805,7 @@ void RenderWidgetHostViewWin::OnPaint(HDC dc) {
if (backing_store) {
gfx::Rect bitmap_rect(gfx::Point(), backing_store->size());
- bool manage_colors = BackingStore::ColorManagementEnabled();
+ bool manage_colors = BackingStoreWin::ColorManagementEnabled();
if (manage_colors)
SetICMMode(paint_dc.m_hDC, ICM_ON);
diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.h b/chrome/browser/renderer_host/render_widget_host_view_win.h
index 3b54064..f86d08a 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_win.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_win.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 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.
@@ -11,6 +11,7 @@
#include <atlmisc.h>
#include "base/scoped_comptr_win.h"
+#include "base/scoped_ptr.h"
#include "base/task.h"
#include "chrome/browser/ime_input.h"
#include "chrome/browser/renderer_host/render_widget_host_view.h"
@@ -27,6 +28,7 @@ class Message;
class BackingStore;
class RenderWidgetHost;
+class GpuViewHostWin;
typedef CWinTraits<WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0>
RenderWidgetHostHWNDTraits;
@@ -59,6 +61,8 @@ class RenderWidgetHostViewWin
explicit RenderWidgetHostViewWin(RenderWidgetHost* widget);
virtual ~RenderWidgetHostViewWin();
+ void CreateWnd(HWND parent);
+
DECLARE_WND_CLASS_EX(kRenderWidgetHostHWNDClass, CS_DBLCLKS, 0);
BEGIN_MSG_MAP(RenderWidgetHostHWND)
@@ -139,7 +143,7 @@ class RenderWidgetHostViewWin
LRESULT OnCreate(CREATESTRUCT* create_struct);
void OnActivate(UINT, BOOL, HWND);
void OnDestroy();
- void OnPaint(HDC dc);
+ void OnPaint(HDC unused_dc);
void OnNCPaint(HRGN update_region);
LRESULT OnEraseBkgnd(HDC dc);
LRESULT OnSetCursor(HWND window, UINT hittest_code, UINT mouse_message_id);
@@ -224,6 +228,10 @@ class RenderWidgetHostViewWin
// The associated Model.
RenderWidgetHost* render_widget_host_;
+ // If we're doing out-of-process painting, this member will be non-NULL,
+ // indicating the gpu view we're using for the painting.
+ scoped_ptr<GpuViewHostWin> gpu_view_host_;
+
// The cursor for the page. This is passed up from the renderer.
WebCursor current_cursor_;
diff --git a/chrome/browser/renderer_host/test/test_backing_store.cc b/chrome/browser/renderer_host/test/test_backing_store.cc
new file mode 100644
index 0000000..d90c7fd
--- /dev/null
+++ b/chrome/browser/renderer_host/test/test_backing_store.cc
@@ -0,0 +1,31 @@
+// 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/test/test_backing_store.h"
+
+TestBackingStore::TestBackingStore(RenderWidgetHost* widget,
+ const gfx::Size& size)
+ : BackingStore(widget, size) {
+}
+
+TestBackingStore::~TestBackingStore() {
+}
+
+void TestBackingStore::PaintToBackingStore(
+ RenderProcessHost* process,
+ TransportDIB::Id bitmap,
+ const gfx::Rect& bitmap_rect,
+ const std::vector<gfx::Rect>& copy_rects,
+ bool* painted_synchronously) {
+}
+
+bool TestBackingStore::CopyFromBackingStore(const gfx::Rect& rect,
+ skia::PlatformCanvas* output) {
+ return false;
+}
+
+void TestBackingStore::ScrollBackingStore(int dx, int dy,
+ const gfx::Rect& clip_rect,
+ const gfx::Size& view_size) {
+}
diff --git a/chrome/browser/renderer_host/test/test_backing_store.h b/chrome/browser/renderer_host/test/test_backing_store.h
new file mode 100644
index 0000000..41deb4c
--- /dev/null
+++ b/chrome/browser/renderer_host/test/test_backing_store.h
@@ -0,0 +1,31 @@
+// 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_TEST_TEST_BACKING_STORE_H_
+#define CHROME_BROWSER_RENDERER_HOST_TEST_TEST_BACKING_STORE_H_
+
+#include "base/basictypes.h"
+#include "chrome/browser/renderer_host/backing_store.h"
+
+class TestBackingStore : public BackingStore {
+ public:
+ TestBackingStore(RenderWidgetHost* widget, const gfx::Size& size);
+ virtual ~TestBackingStore();
+
+ // BackingStore implementation.
+ virtual void PaintToBackingStore(RenderProcessHost* process,
+ TransportDIB::Id bitmap,
+ const gfx::Rect& bitmap_rect,
+ const std::vector<gfx::Rect>& copy_rects,
+ bool* painted_synchronously);
+ virtual bool CopyFromBackingStore(const gfx::Rect& rect,
+ skia::PlatformCanvas* output);
+ virtual void ScrollBackingStore(int dx, int dy,
+ const gfx::Rect& clip_rect,
+ const gfx::Size& view_size);
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestBackingStore);
+};
+
+#endif // CHROME_BROWSER_RENDERER_HOST_TEST_TEST_BACKING_STORE_H_
diff --git a/chrome/browser/renderer_host/test/test_render_view_host.cc b/chrome/browser/renderer_host/test/test_render_view_host.cc
index 720f51e..095c2e1 100644
--- a/chrome/browser/renderer_host/test/test_render_view_host.cc
+++ b/chrome/browser/renderer_host/test/test_render_view_host.cc
@@ -5,7 +5,7 @@
#include "chrome/browser/renderer_host/test/test_render_view_host.h"
#include "base/gfx/rect.h"
-#include "chrome/browser/renderer_host/backing_store.h"
+#include "chrome/browser/renderer_host/test/test_backing_store.h"
#include "chrome/browser/tab_contents/test_tab_contents.h"
#include "chrome/common/render_messages.h"
@@ -74,7 +74,7 @@ TestRenderWidgetHostView::TestRenderWidgetHostView(RenderWidgetHost* rwh)
BackingStore* TestRenderWidgetHostView::AllocBackingStore(
const gfx::Size& size) {
- return new BackingStore(rwh_, size);
+ return new TestBackingStore(rwh_, size);
}
#if defined(OS_MACOSX)
diff --git a/chrome/browser/sandbox_policy.cc b/chrome/browser/sandbox_policy.cc
index 4af55a6..ce137e0 100644
--- a/chrome/browser/sandbox_policy.cc
+++ b/chrome/browser/sandbox_policy.cc
@@ -350,6 +350,8 @@ base::ProcessHandle StartProcessWithAccess(CommandLine* cmd_line,
type = ChildProcessInfo::NACL_PROCESS;
} else if (type_str == switches::kUtilityProcess) {
type = ChildProcessInfo::UTILITY_PROCESS;
+ } else if (type_str == switches::kGpuProcess) {
+ type = ChildProcessInfo::GPU_PROCESS;
} else {
NOTREACHED();
return 0;
diff --git a/chrome/browser/tab_contents/thumbnail_generator.cc b/chrome/browser/tab_contents/thumbnail_generator.cc
index 1a5c5c4..ccd781e 100644
--- a/chrome/browser/tab_contents/thumbnail_generator.cc
+++ b/chrome/browser/tab_contents/thumbnail_generator.cc
@@ -7,8 +7,10 @@
#include <algorithm>
#include "app/gfx/skbitmap_operations.h"
+#include "base/gfx/rect.h"
#include "base/histogram.h"
#include "base/time.h"
+#include "build/build_config.h"
#include "chrome/browser/renderer_host/backing_store.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/common/notification_service.h"
@@ -87,22 +89,6 @@ WidgetThumbnail* GetDataForHost(RenderWidgetHost* host) {
return GetThumbnailAccessor()->GetProperty(host->property_bag());
}
-#if defined(OS_WIN)
-
-// PlatformDevices/Canvases can't be copied like a regular SkBitmap (at least
-// on Windows). So the second parameter is the canvas to draw into. It should
-// be sized to the size of the backing store.
-void GetBitmapForBackingStore(BackingStore* backing_store,
- skia::PlatformCanvas* canvas) {
- HDC dc = canvas->beginPlatformPaint();
- BitBlt(dc, 0, 0,
- backing_store->size().width(), backing_store->size().height(),
- backing_store->hdc(), 0, 0, SRCCOPY);
- canvas->endPlatformPaint();
-}
-
-#endif
-
// Creates a downsampled thumbnail for the given backing store. The returned
// bitmap will be isNull if there was an error creating it.
SkBitmap GetThumbnailForBackingStore(BackingStore* backing_store) {
@@ -110,48 +96,26 @@ SkBitmap GetThumbnailForBackingStore(BackingStore* backing_store) {
SkBitmap result;
- // TODO(brettw) write this for other platforms. If you enable this, be sure
- // to also enable the unit tests for the same platform in
- // thumbnail_generator_unittest.cc
-#if defined(OS_WIN)
// Get the bitmap as a Skia object so we can resample it. This is a large
// allocation and we can tolerate failure here, so give up if the allocation
// fails.
skia::PlatformCanvas temp_canvas;
- if (!temp_canvas.initialize(backing_store->size().width(),
- backing_store->size().height(), true))
+ if (!backing_store->CopyFromBackingStore(gfx::Rect(gfx::Point(0, 0),
+ backing_store->size()),
+ &temp_canvas))
return result;
- GetBitmapForBackingStore(backing_store, &temp_canvas);
-
- // Get the bitmap out of the canvas and resample it. It would be nice if this
- // whole Windows-specific block could be put into a function, but the memory
- // management wouldn't work out because the bitmap is a PlatformDevice which
- // can't actually be copied.
const SkBitmap& bmp = temp_canvas.getTopPlatformDevice().accessBitmap(false);
-
-#elif defined(OS_LINUX)
- SkBitmap bmp = backing_store->PaintRectToBitmap(
- gfx::Rect(0, 0,
- backing_store->size().width(), backing_store->size().height()));
-
-#elif defined(OS_MACOSX)
- SkBitmap bmp;
- NOTIMPLEMENTED();
-#endif
-
result = SkBitmapOperations::DownsampleByTwoUntilSize(bmp, kThumbnailWidth,
kThumbnailHeight);
-#if defined(OS_WIN)
// This is a bit subtle. SkBitmaps are refcounted, but the magic ones in
- // PlatformCanvas on Windows can't be ssigned to SkBitmap with proper
+ // PlatformCanvas can't be ssigned to SkBitmap with proper
// refcounting. If the bitmap doesn't change, then the downsampler will
// return the input bitmap, which will be the reference to the weird
// PlatformCanvas one insetad of a regular one. To get a regular refcounted
// bitmap, we need to copy it.
if (bmp.width() == result.width() && bmp.height() == result.height())
bmp.copyTo(&result, SkBitmap::kARGB_8888_Config);
-#endif
HISTOGRAM_TIMES(kThumbnailHistogramName,
base::TimeTicks::Now() - begin_compute_thumbnail);
diff --git a/chrome/browser/views/tab_contents/tab_contents_view_win.cc b/chrome/browser/views/tab_contents/tab_contents_view_win.cc
index b46290b..a6f8b3e 100644
--- a/chrome/browser/views/tab_contents/tab_contents_view_win.cc
+++ b/chrome/browser/views/tab_contents/tab_contents_view_win.cc
@@ -107,7 +107,7 @@ RenderWidgetHostView* TabContentsViewWin::CreateViewForWidget(
RenderWidgetHostViewWin* view =
new RenderWidgetHostViewWin(render_widget_host);
- view->Create(GetNativeView());
+ view->CreateWnd(GetNativeView());
view->ShowWindow(SW_SHOW);
return view;
}
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 49003b4..3e280a9 100755
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -1,4 +1,4 @@
-# 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.
@@ -25,6 +25,7 @@
'common',
'browser',
'debugger',
+ 'chrome_gpu',
'renderer',
'syncapi',
'utility',
@@ -513,6 +514,38 @@
],
},
{
+ 'target_name': 'chrome_gpu',
+ 'type': '<(library)',
+ 'msvs_guid': 'F10F1ECD-D84D-4C33-8468-9DDFE19F4D8A',
+ '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',
+ ],
+ }]
+ ],
+ 'sources': [
+ 'gpu/gpu_main.cc',
+ 'gpu/gpu_process.cc',
+ 'gpu/gpu_process.h',
+ 'gpu/gpu_thread.cc',
+ 'gpu/gpu_thread.h',
+ ],
+ 'include_dirs': [
+ '..',
+ ],
+ },
+ {
'target_name': 'worker',
'type': '<(library)',
'msvs_guid': 'C78D02D0-A366-4EC6-A248-AA8E64C4BA18',
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index d567984..2625ca9 100755
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -813,6 +813,8 @@
'browser/google_url_tracker.h',
'browser/google_util.cc',
'browser/google_util.h',
+ 'browser/gpu_process_host.cc',
+ 'browser/gpu_process_host.h',
'browser/gtk/about_chrome_dialog.cc',
'browser/gtk/about_chrome_dialog.h',
'browser/gtk/back_forward_button_gtk.cc',
@@ -1327,12 +1329,18 @@
'browser/renderer_host/async_resource_handler.h',
'browser/renderer_host/audio_renderer_host.cc',
'browser/renderer_host/audio_renderer_host.h',
+ 'browser/renderer_host/backing_store.cc',
'browser/renderer_host/backing_store.h',
'browser/renderer_host/backing_store_manager.cc',
'browser/renderer_host/backing_store_manager.h',
+ 'browser/renderer_host/backing_store_mac.h',
'browser/renderer_host/backing_store_mac.mm',
+ 'browser/renderer_host/backing_store_proxy.cc',
+ 'browser/renderer_host/backing_store_proxy.h',
'browser/renderer_host/backing_store_win.cc',
+ 'browser/renderer_host/backing_store_win.h',
'browser/renderer_host/backing_store_x.cc',
+ 'browser/renderer_host/backing_store_x.h',
'browser/renderer_host/browser_render_process_host.cc',
'browser/renderer_host/browser_render_process_host.h',
'browser/renderer_host/buffered_resource_handler.cc',
@@ -1346,6 +1354,8 @@
'browser/renderer_host/download_throttling_resource_handler.cc',
'browser/renderer_host/download_throttling_resource_handler.h',
'browser/renderer_host/global_request_id.h',
+ 'browser/renderer_host/gpu_view_host_win.cc',
+ 'browser/renderer_host/gpu_view_host_win.h',
'browser/renderer_host/gtk_im_context_wrapper.cc',
'browser/renderer_host/gtk_im_context_wrapper.h',
'browser/renderer_host/gtk_key_bindings_handler.cc',
@@ -1921,6 +1931,8 @@
# Windows-specific files.
'browser/password_manager/password_store_win.cc',
'browser/password_manager/password_store_win.h',
+ 'browser/renderer_host/backing_store_proxy.cc',
+ 'browser/renderer_host/backing_store_proxy.h',
],
'sources': [
'browser/crash_handler_host_linux.h',
@@ -1972,6 +1984,8 @@
'browser/password_manager/password_store_kwallet.cc',
'browser/password_manager/password_store_win.cc',
'browser/password_manager/password_store_win.h',
+ 'browser/renderer_host/backing_store_proxy.cc',
+ 'browser/renderer_host/backing_store_proxy.h',
'browser/views/extensions/extension_shelf.cc',
'browser/views/extensions/extension_shelf.h',
'browser/views/extensions/extension_view.cc',
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi
index 0624d4a..adfa960b 100644
--- a/chrome/chrome_common.gypi
+++ b/chrome/chrome_common.gypi
@@ -53,6 +53,8 @@
'common/debug_flags.h',
'common/devtools_messages.h',
'common/devtools_messages_internal.h',
+ 'common/gpu_messages.h',
+ 'common/gpu_messages_internal.h',
'common/logging_chrome.cc',
'common/logging_chrome.h',
'common/main_function_params.h',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index ea66614..d00af61 100755
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -73,6 +73,8 @@
'browser/net/url_request_mock_net_error_job.h',
'browser/renderer_host/mock_render_process_host.cc',
'browser/renderer_host/mock_render_process_host.h',
+ 'browser/renderer_host/test/test_backing_store.cc',
+ 'browser/renderer_host/test/test_backing_store.h',
'browser/renderer_host/test/test_render_view_host.cc',
'browser/renderer_host/test/test_render_view_host.h',
'browser/tab_contents/test_tab_contents.cc',
diff --git a/chrome/common/child_process_host.h b/chrome/common/child_process_host.h
index 94bdafd..1ca547b 100644
--- a/chrome/common/child_process_host.h
+++ b/chrome/common/child_process_host.h
@@ -69,6 +69,8 @@ class ChildProcessHost : public ResourceDispatcherHost::Receiver,
};
protected:
+ // The resource_dispatcher_host may be NULL to indicate none is needed for
+ // this process type.
ChildProcessHost(ProcessType type,
ResourceDispatcherHost* resource_dispatcher_host);
@@ -127,7 +129,10 @@ class ChildProcessHost : public ResourceDispatcherHost::Receiver,
};
ListenerHook listener_;
+
+ // May be NULL if this current process has no resource dispatcher host.
ResourceDispatcherHost* resource_dispatcher_host_;
+
bool opening_channel_; // True while we're waiting the channel to be opened.
scoped_ptr<IPC::Channel> channel_;
std::string channel_id_;
diff --git a/chrome/common/child_process_info.h b/chrome/common/child_process_info.h
index 50d1d0d..5726675 100644
--- a/chrome/common/child_process_info.h
+++ b/chrome/common/child_process_info.h
@@ -24,7 +24,8 @@ class ChildProcessInfo {
UTILITY_PROCESS,
PROFILE_IMPORT_PROCESS,
ZYGOTE_PROCESS,
- SANDBOX_HELPER_PROCESS
+ SANDBOX_HELPER_PROCESS,
+ GPU_PROCESS
};
ChildProcessInfo(const ChildProcessInfo& original);
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index af88125..251b382 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -1,4 +1,4 @@
-// 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.
@@ -205,7 +205,7 @@ const char kEnableFastback[] = "enable-fastback";
const char kEnableFileCookies[] = "enable-file-cookies";
// Enable Geolocation support.
-const char kEnableGeolocation[] = "enable-geolocation";
+const char kEnableGeolocation[] = "enable-geolocation";
// Enable the GPU plugin and Pepper 3D rendering.
const char kEnableGPUPlugin[] = "enable-gpu-plugin";
@@ -298,6 +298,9 @@ const char kFirstRun[] = "first-run";
// current details.
const char kForceFieldTestNameAndValue[] = "force-fieldtest";
+// Makes this process a GPU sub-process.
+const char kGpuProcess[] = "gpu-process";
+
// Make Windows happy by allowing it to show "Enable access to this program"
// checkbox in Add/Remove Programs->Set Program Access and Defaults. This
// only shows an error box because the only way to hide Chrome is by
@@ -325,12 +328,6 @@ const char kInternalNaCl[] = "internal-nacl";
// Runs a trusted Pepper plugin inside the renderer process.
const char kInternalPepper[] = "internal-pepper";
-#ifndef NDEBUG
-// Makes sure any sync login attempt will fail with an error. (Only
-// used for testing.)
-const char kInvalidateSyncLogin[] = "invalidate-sync-login";
-#endif
-
// Specifies the flags passed to JS engine
const char kJavaScriptFlags[] = "js-flags";
@@ -733,6 +730,10 @@ const char kKioskMode[] = "kiosk";
#ifndef NDEBUG
// Debug only switch to specify which gears plugin dll to load.
const char kGearsPluginPathOverride[] = "gears-plugin-path";
+
+// Makes sure any sync login attempt will fail with an error. (Only
+// used for testing.)
+const char kInvalidateSyncLogin[] = "invalidate-sync-login";
#endif
// -----------------------------------------------------------------------------
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 7e3deaf..15b1975 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 kGpuProcess[];
extern const char kHideIcons[];
extern const char kHomePage[];
extern const char kImport[];
@@ -103,9 +104,6 @@ extern const char kInProcessPlugins[];
extern const char kIncognito[];
extern const char kInternalNaCl[];
extern const char kInternalPepper[];
-#ifndef NDEBUG
-extern const char kInvalidateSyncLogin[];
-#endif
extern const char kJavaScriptFlags[];
extern const char kLoadExtension[];
extern const char kLoadPlugin[];
@@ -221,6 +219,7 @@ extern const char kKioskMode[];
#ifndef NDEBUG
extern const char kGearsPluginPathOverride[];
+extern const char kInvalidateSyncLogin[];
#endif
// DON'T ADD RANDOM STUFF HERE. Put it in the main section above in
diff --git a/chrome/common/gpu_messages.h b/chrome/common/gpu_messages.h
new file mode 100644
index 0000000..52e3d6f
--- /dev/null
+++ b/chrome/common/gpu_messages.h
@@ -0,0 +1,28 @@
+// 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_MESSAGES_H_
+#define CHROME_COMMON_GPU_MESSAGES_H_
+
+#include <vector>
+
+#include "app/gfx/native_widget_types.h"
+#include "base/basictypes.h"
+#include "base/gfx/rect.h"
+#include "base/gfx/size.h"
+#include "chrome/common/common_param_traits.h"
+#include "chrome/common/transport_dib.h"
+
+namespace IPC {
+
+// Potential new structures for messages go here.
+
+} // namespace IPC
+
+#define MESSAGES_INTERNAL_FILE \
+ "chrome/common/gpu_messages_internal.h"
+#include "ipc/ipc_message_macros.h"
+
+#endif // CHROME_COMMON_GPU_MESSAGES_H_
+
diff --git a/chrome/common/gpu_messages_internal.h b/chrome/common/gpu_messages_internal.h
new file mode 100644
index 0000000..73a82f1
--- /dev/null
+++ b/chrome/common/gpu_messages_internal.h
@@ -0,0 +1,59 @@
+// 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.
+
+// This header is meant to be included in multiple passes, hence no traditional
+// header guard. It is included by backing_store_messages_internal.h
+// See ipc_message_macros.h for explanation of the macros and passes.
+
+// This file needs to be included again, even though we're actually included
+// from it via utility_messages.h.
+#include "ipc/ipc_message_macros.h"
+
+//------------------------------------------------------------------------------
+// Backing Store Messages
+// These are messages from the browser to the GPU process.
+IPC_BEGIN_MESSAGES(Gpu)
+
+ IPC_MESSAGE_CONTROL2(GpuMsg_NewRenderWidgetHostView,
+ gfx::NativeViewId, /* parent window */
+ int32 /* view_id */)
+
+ // Creates a new backing store.
+ IPC_MESSAGE_ROUTED2(GpuMsg_NewBackingStore,
+ int32, /* backing_store_id */
+ gfx::Size /* size */)
+
+ // Updates the backing store with the given bitmap. The GPU process will send
+ // back a GpuHostMsg_PaintToBackingStore_ACK after the paint is complete to
+ // let the caller know the TransportDIB can be freed or reused.
+ IPC_MESSAGE_ROUTED4(GpuMsg_PaintToBackingStore,
+ base::ProcessId, /* process */
+ TransportDIB::Id, /* bitmap */
+ gfx::Rect, /* bitmap_rect */
+ std::vector<gfx::Rect>) /* copy_rects */
+
+
+ IPC_MESSAGE_ROUTED4(GpuMsg_ScrollBackingStore,
+ int, /* dx */
+ int, /* dy */
+ gfx::Rect, /* clip_rect */
+ gfx::Size) /* view_size */
+
+IPC_END_MESSAGES(Gpu)
+
+//------------------------------------------------------------------------------
+// Backing Store Host Messagse
+// These are messages from the GPU process to the browser.
+IPC_BEGIN_MESSAGES(GpuHost)
+
+ // This message is sent in response to BackingStoreMsg_New to tell the host
+ // about the child window that was just created.
+ IPC_MESSAGE_ROUTED1(GpuHostMsg_CreatedRenderWidgetHostView,
+ gfx::NativeViewId)
+
+ // Send in response to GpuMsg_PaintToBackingStore, see that for more.
+ IPC_MESSAGE_ROUTED0(GpuHostMsg_PaintToBackingStore_ACK)
+
+IPC_END_MESSAGES(GpuHost)
+
diff --git a/chrome/gpu/gpu_backing_store.cc b/chrome/gpu/gpu_backing_store.cc
new file mode 100644
index 0000000..a5fafe2
--- /dev/null
+++ b/chrome/gpu/gpu_backing_store.cc
@@ -0,0 +1,185 @@
+// 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.h"
+
+#include "app/gfx/gdi_util.h"
+#include "app/win_util.h"
+#include "base/logging.h"
+#include "chrome/common/gpu_messages.h"
+#include "chrome/gpu/gpu_view_win.h"
+#include "chrome/gpu/gpu_thread.h"
+
+namespace {
+
+// Creates a dib conforming to the height/width/section parameters passed in.
+HANDLE CreateDIB(HDC dc, int width, int height, int color_depth) {
+ BITMAPV5HEADER hdr = {0};
+ ZeroMemory(&hdr, sizeof(BITMAPV5HEADER));
+
+ // These values are shared with gfx::PlatformDevice
+ hdr.bV5Size = sizeof(BITMAPINFOHEADER);
+ hdr.bV5Width = width;
+ hdr.bV5Height = -height; // minus means top-down bitmap
+ hdr.bV5Planes = 1;
+ hdr.bV5BitCount = color_depth;
+ hdr.bV5Compression = BI_RGB; // no compression
+ hdr.bV5SizeImage = 0;
+ hdr.bV5XPelsPerMeter = 1;
+ hdr.bV5YPelsPerMeter = 1;
+ hdr.bV5ClrUsed = 0;
+ hdr.bV5ClrImportant = 0;
+
+
+ void* data = NULL;
+ HANDLE dib = CreateDIBSection(dc, reinterpret_cast<BITMAPINFO*>(&hdr),
+ 0, &data, NULL, 0);
+ DCHECK(data);
+ return dib;
+}
+
+void CallStretchDIBits(HDC hdc, int dest_x, int dest_y, int dest_w, int dest_h,
+ int src_x, int src_y, int src_w, int src_h, void* pixels,
+ const BITMAPINFO* bitmap_info) {
+ // When blitting a rectangle that touches the bottom, left corner of the
+ // bitmap, StretchDIBits looks at it top-down! For more details, see
+ // http://wiki.allegro.cc/index.php?title=StretchDIBits.
+ int rv;
+ int bitmap_h = -bitmap_info->bmiHeader.biHeight;
+ int bottom_up_src_y = bitmap_h - src_y - src_h;
+ if (bottom_up_src_y == 0 && src_x == 0 && src_h != bitmap_h) {
+ rv = StretchDIBits(hdc,
+ dest_x, dest_h + dest_y - 1, dest_w, -dest_h,
+ src_x, bitmap_h - src_y + 1, src_w, -src_h,
+ pixels, bitmap_info, DIB_RGB_COLORS, SRCCOPY);
+ } else {
+ rv = StretchDIBits(hdc,
+ dest_x, dest_y, dest_w, dest_h,
+ src_x, bottom_up_src_y, src_w, src_h,
+ pixels, bitmap_info, DIB_RGB_COLORS, SRCCOPY);
+ }
+ DCHECK(rv != GDI_ERROR);
+}
+
+} // namespace
+
+
+GpuBackingStore::GpuBackingStore(GpuViewWin* view,
+ GpuThread* gpu_thread,
+ int32 routing_id,
+ const gfx::Size& size)
+ : view_(view),
+ gpu_thread_(gpu_thread),
+ routing_id_(routing_id),
+ size_(size) {
+ gpu_thread_->AddRoute(routing_id_, this);
+
+ HDC screen_dc = ::GetDC(NULL);
+ color_depth_ = ::GetDeviceCaps(screen_dc, BITSPIXEL);
+ // Color depths less than 16 bpp require a palette to be specified. Instead,
+ // we specify the desired color depth as 16 which lets the OS to come up
+ // with an approximation.
+ if (color_depth_ < 16)
+ color_depth_ = 16;
+ hdc_ = CreateCompatibleDC(screen_dc);
+ ReleaseDC(NULL, screen_dc);
+}
+
+GpuBackingStore::~GpuBackingStore() {
+ gpu_thread_->RemoveRoute(routing_id_);
+
+ DCHECK(hdc_);
+ if (original_bitmap_) {
+ SelectObject(hdc_, original_bitmap_);
+ }
+ if (backing_store_dib_) {
+ DeleteObject(backing_store_dib_);
+ backing_store_dib_ = NULL;
+ }
+ DeleteDC(hdc_);
+}
+
+void GpuBackingStore::OnMessageReceived(const IPC::Message& msg) {
+ IPC_BEGIN_MESSAGE_MAP(GpuBackingStore, 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 GpuBackingStore::OnChannelError() {
+ // FIXME(brettw) does this mean we aren't getting any more messages and we
+ // should delete outselves?
+}
+
+void GpuBackingStore::OnPaintToBackingStore(
+ base::ProcessId source_process_id,
+ TransportDIB::Id id,
+ const gfx::Rect& bitmap_rect,
+ const std::vector<gfx::Rect>& copy_rects) {
+ HANDLE source_process_handle = OpenProcess(PROCESS_ALL_ACCESS,
+ FALSE, source_process_id);
+ CHECK(source_process_handle);
+
+ // On Windows we need to duplicate the handle from the remote process.
+ // See BrowserRenderProcessHost::MapTransportDIB for how to do this on other
+ // platforms.
+ HANDLE section = win_util::GetSectionFromProcess(
+ id.handle, source_process_handle, false /* read write */);
+ CHECK(section);
+ TransportDIB* dib = TransportDIB::Map(section);
+ CHECK(dib);
+
+ if (!backing_store_dib_) {
+ backing_store_dib_ = CreateDIB(hdc_, size_.width(),
+ size_.height(), color_depth_);
+ if (!backing_store_dib_) {
+ NOTREACHED();
+
+ // TODO(brettw): do this in such a way that we can't forget to
+ // send the ACK.
+ gpu_thread_->Send(new GpuHostMsg_PaintToBackingStore_ACK(routing_id_));
+ return;
+ }
+ original_bitmap_ = SelectObject(hdc_, backing_store_dib_);
+ }
+
+ BITMAPINFOHEADER hdr;
+ gfx::CreateBitmapHeader(bitmap_rect.width(), bitmap_rect.height(), &hdr);
+ // Account for a bitmap_rect that exceeds the bounds of our view
+ gfx::Rect view_rect(0, 0, size_.width(), size_.height());
+
+ for (size_t i = 0; i < copy_rects.size(); i++) {
+ gfx::Rect paint_rect = view_rect.Intersect(copy_rects[i]);
+ CallStretchDIBits(hdc_,
+ paint_rect.x(),
+ paint_rect.y(),
+ paint_rect.width(),
+ paint_rect.height(),
+ paint_rect.x() - bitmap_rect.x(),
+ paint_rect.y() - bitmap_rect.y(),
+ paint_rect.width(),
+ paint_rect.height(),
+ dib->memory(),
+ reinterpret_cast<BITMAPINFO*>(&hdr));
+ view_->InvalidateRect(&paint_rect.ToRECT());
+ }
+
+ CloseHandle(source_process_handle);
+ 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) {
+ RECT damaged_rect, r = clip_rect.ToRECT();
+ ScrollDC(hdc_, dx, dy, NULL, &r, NULL, &damaged_rect);
+
+ // TODO(darin): this doesn't work if dx and dy are both non-zero!
+ DCHECK(dx == 0 || dy == 0);
+
+ view_->DidScrollBackingStoreRect(dx, dy, clip_rect);
+}
diff --git a/chrome/gpu/gpu_backing_store.h b/chrome/gpu/gpu_backing_store.h
new file mode 100644
index 0000000..bfe9941
--- /dev/null
+++ b/chrome/gpu/gpu_backing_store.h
@@ -0,0 +1,74 @@
+// 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_H_
+#define CHROME_GPU_GPU_BACKING_STORE_H_
+
+#include <windows.h>
+
+#include <vector>
+
+#include "app/gfx/native_widget_types.h"
+#include "base/basictypes.h"
+#include "base/gfx/size.h"
+#include "chrome/common/transport_dib.h"
+#include "ipc/ipc_channel.h"
+
+class GpuThread;
+class GpuViewWin;
+
+namespace gfx {
+class Rect;
+class Size;
+}
+
+class GpuBackingStore : public IPC::Channel::Listener {
+ public:
+ GpuBackingStore(GpuViewWin* view,
+ GpuThread* gpu_thread,
+ int32 routing_id,
+ const gfx::Size& size);
+ ~GpuBackingStore();
+
+ gfx::Size size() const { return size_; }
+ HDC hdc() const { return hdc_; }
+
+ // 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);
+
+ GpuViewWin* view_;
+
+ GpuThread* gpu_thread_;
+ int32 routing_id_;
+
+ gfx::Size size_;
+
+ // The backing store dc.
+ HDC hdc_;
+
+ // Handle to the backing store dib.
+ HANDLE backing_store_dib_;
+
+ // Handle to the original bitmap in the dc.
+ HANDLE original_bitmap_;
+
+ // Number of bits per pixel of the screen.
+ int color_depth_;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuBackingStore);
+};
+
+#endif // CHROME_GPU_GPU_BACKING_STORE_H_
diff --git a/chrome/gpu/gpu_main.cc b/chrome/gpu/gpu_main.cc
new file mode 100644
index 0000000..e60cffa
--- /dev/null
+++ b/chrome/gpu/gpu_main.cc
@@ -0,0 +1,38 @@
+// 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 "base/message_loop.h"
+#include "build/build_config.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/main_function_params.h"
+#include "chrome/gpu/gpu_process.h"
+#include "chrome/gpu/gpu_thread.h"
+
+#if defined(OS_WIN)
+#include "app/win_util.h"
+#endif
+
+// Main function for starting the Gpu process.
+int GpuMain(const MainFunctionParams& parameters) {
+#if defined(USE_LINUX_BREAKPAD)
+ // Needs to be called after we have chrome::DIR_USER_DATA.
+ InitCrashReporter();
+#endif
+
+ MessageLoop main_message_loop(MessageLoop::TYPE_UI);
+ std::wstring app_name = chrome::kBrowserAppName;
+ PlatformThread::SetName(WideToASCII(app_name + L"_GpuMain").c_str());
+
+#if defined(OS_WIN)
+ win_util::ScopedCOMInitializer com_initializer;
+#endif
+
+ GpuProcess gpu_process;
+ gpu_process.set_main_thread(new GpuThread());
+
+ main_message_loop.Run();
+
+ return 0;
+}
+
diff --git a/chrome/gpu/gpu_process.cc b/chrome/gpu/gpu_process.cc
new file mode 100644
index 0000000..ada83c8
--- /dev/null
+++ b/chrome/gpu/gpu_process.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/gpu_process.h"
+
+GpuProcess::GpuProcess() {
+}
+
+GpuProcess::~GpuProcess() {
+}
diff --git a/chrome/gpu/gpu_process.h b/chrome/gpu/gpu_process.h
new file mode 100644
index 0000000..92c73a6
--- /dev/null
+++ b/chrome/gpu/gpu_process.h
@@ -0,0 +1,19 @@
+// 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_PROCESS_H_
+#define CHROME_GPU_GPU_PROCESS_H_
+
+#include "chrome/common/child_process.h"
+
+class GpuProcess : public ChildProcess {
+ public:
+ GpuProcess();
+ ~GpuProcess();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GpuProcess);
+};
+
+#endif // CHROME_GPU_GPU_PROCESS_H_
diff --git a/chrome/gpu/gpu_thread.cc b/chrome/gpu/gpu_thread.cc
new file mode 100644
index 0000000..d143cbc
--- /dev/null
+++ b/chrome/gpu/gpu_thread.cc
@@ -0,0 +1,38 @@
+// 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_thread.h"
+
+#include "build/build_config.h"
+#include "chrome/common/gpu_messages.h"
+
+#if defined(OS_WIN)
+#include "chrome/gpu/gpu_view_win.h"
+#endif
+
+GpuThread::GpuThread() {
+}
+
+GpuThread::~GpuThread() {
+}
+
+void GpuThread::OnControlMessageReceived(const IPC::Message& msg) {
+ bool msg_is_ok = true;
+ IPC_BEGIN_MESSAGE_MAP_EX(GpuThread, msg, msg_is_ok)
+ IPC_MESSAGE_HANDLER(GpuMsg_NewRenderWidgetHostView,
+ OnNewRenderWidgetHostView)
+ IPC_END_MESSAGE_MAP_EX()
+}
+
+void GpuThread::OnNewRenderWidgetHostView(gfx::NativeViewId parent_window,
+ int32 routing_id) {
+#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);
+#else
+ NOTIMPLEMENTED();
+#endif
+}
diff --git a/chrome/gpu/gpu_thread.h b/chrome/gpu/gpu_thread.h
new file mode 100644
index 0000000..3f25b00
--- /dev/null
+++ b/chrome/gpu/gpu_thread.h
@@ -0,0 +1,28 @@
+// 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_THREAD_H_
+#define CHROME_GPU_GPU_THREAD_H_
+
+#include "app/gfx/native_widget_types.h"
+#include "base/basictypes.h"
+#include "chrome/common/child_thread.h"
+
+class GpuThread : public ChildThread {
+ public:
+ GpuThread();
+ ~GpuThread();
+
+ private:
+ // ChildThread overrides.
+ virtual void OnControlMessageReceived(const IPC::Message& msg);
+
+ // Message handlers.
+ void OnNewRenderWidgetHostView(gfx::NativeViewId parent_window,
+ int32 routing_id);
+
+ DISALLOW_COPY_AND_ASSIGN(GpuThread);
+};
+
+#endif // CHROME_GPU_GPU_THREAD_H_
diff --git a/chrome/gpu/gpu_view_win.cc b/chrome/gpu/gpu_view_win.cc
new file mode 100644
index 0000000..e94c695
--- /dev/null
+++ b/chrome/gpu/gpu_view_win.cc
@@ -0,0 +1,158 @@
+// 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_win.h"
+
+#include "chrome/common/gpu_messages.h"
+#include "chrome/gpu/gpu_backing_store.h"
+#include "chrome/gpu/gpu_thread.h"
+
+namespace {
+
+void DrawBackground(const RECT& dirty_rect, CPaintDC* dc) {
+ HBRUSH white_brush = reinterpret_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
+ dc->FillRect(&dirty_rect, white_brush);
+}
+
+void DrawResizeCorner(const RECT& dirty_rect, HDC dc) {
+ // TODO(brettw): implement this.
+}
+
+} // namespace
+
+GpuViewWin::GpuViewWin(GpuThread* gpu_thread,
+ gfx::NativeViewId parent_window,
+ int32 routing_id)
+ : gpu_thread_(gpu_thread),
+ routing_id_(routing_id),
+ parent_window_(gfx::NativeViewFromId(parent_window)) {
+ gpu_thread_->AddRoute(routing_id_, this);
+ Create(gfx::NativeViewFromId(parent_window));
+ SetWindowText(L"GPU window");
+ ShowWindow(SW_SHOW);
+}
+
+GpuViewWin::~GpuViewWin() {
+ gpu_thread_->RemoveRoute(routing_id_);
+ // TODO(brettw) may want to delete any dangling backing stores, or perhaps
+ // assert if one still exists.
+}
+
+void GpuViewWin::OnMessageReceived(const IPC::Message& msg) {
+ IPC_BEGIN_MESSAGE_MAP(GpuViewWin, msg)
+ IPC_MESSAGE_HANDLER(GpuMsg_NewBackingStore, OnNewBackingStore)
+ IPC_END_MESSAGE_MAP_EX()
+}
+
+void GpuViewWin::OnChannelConnected(int32 peer_pid) {
+}
+
+void GpuViewWin::OnChannelError() {
+ // TODO(brettw) do we need to delete ourselves now?
+}
+
+void GpuViewWin::DidScrollBackingStoreRect(int dx, int dy,
+ const gfx::Rect& rect) {
+ // We need to pass in SW_INVALIDATE to ScrollWindowEx. The documentation on
+ // MSDN states that it only applies to the HRGN argument, which is wrong.
+ // Not passing in this flag does not invalidate the region which was scrolled
+ // from, thus causing painting issues.
+ RECT clip_rect = rect.ToRECT();
+ ScrollWindowEx(dx, dy, NULL, &clip_rect, NULL, NULL, SW_INVALIDATE);
+}
+
+void GpuViewWin::OnNewBackingStore(int32 routing_id, const gfx::Size& size) {
+ backing_store_.reset(
+ new GpuBackingStore(this, gpu_thread_, routing_id, size));
+ MoveWindow(0, 0, size.width(), size.height(), TRUE);
+}
+
+void GpuViewWin::OnPaint(HDC unused_dc) {
+ // Grab the region to paint before creation of paint_dc since it clears the
+ // damage region.
+ ScopedGDIObject<HRGN> damage_region(CreateRectRgn(0, 0, 0, 0));
+ GetUpdateRgn(damage_region, FALSE);
+
+ CPaintDC paint_dc(m_hWnd);
+
+ gfx::Rect damaged_rect(paint_dc.m_ps.rcPaint);
+ if (damaged_rect.IsEmpty())
+ return;
+
+ if (backing_store_.get()) {
+ gfx::Rect bitmap_rect(gfx::Point(), backing_store_->size());
+
+ // Blit only the damaged regions from the backing store.
+ DWORD data_size = GetRegionData(damage_region, 0, NULL);
+ // TODO(brettw) why is the "+1" necessary here? When I remove it, the
+ // page paints black, but according to the documentation, its not needed.
+ scoped_array<char> region_data_buf(new char[data_size + 1]);
+ RGNDATA* region_data = reinterpret_cast<RGNDATA*>(region_data_buf.get());
+ GetRegionData(damage_region, data_size, region_data);
+
+ RECT* region_rects = reinterpret_cast<RECT*>(region_data->Buffer);
+ for (DWORD i = 0; i < region_data->rdh.nCount; ++i) {
+ gfx::Rect paint_rect = bitmap_rect.Intersect(gfx::Rect(region_rects[i]));
+ if (!paint_rect.IsEmpty()) {
+ DrawResizeCorner(paint_rect.ToRECT(), backing_store_->hdc());
+ BitBlt(paint_dc.m_hDC,
+ paint_rect.x(),
+ paint_rect.y(),
+ paint_rect.width(),
+ paint_rect.height(),
+ backing_store_->hdc(),
+ paint_rect.x(),
+ paint_rect.y(),
+ SRCCOPY);
+ }
+ }
+
+ // Fill the remaining portion of the damaged_rect with the background
+ if (damaged_rect.right() > bitmap_rect.right()) {
+ RECT r;
+ r.left = std::max(bitmap_rect.right(), damaged_rect.x());
+ r.right = damaged_rect.right();
+ r.top = damaged_rect.y();
+ r.bottom = std::min(bitmap_rect.bottom(), damaged_rect.bottom());
+ DrawBackground(r, &paint_dc);
+ }
+ if (damaged_rect.bottom() > bitmap_rect.bottom()) {
+ RECT r;
+ r.left = damaged_rect.x();
+ r.right = damaged_rect.right();
+ r.top = std::max(bitmap_rect.bottom(), damaged_rect.y());
+ r.bottom = damaged_rect.bottom();
+ DrawBackground(r, &paint_dc);
+ }
+ } else {
+ DrawBackground(paint_dc.m_ps.rcPaint, &paint_dc);
+ }
+}
+
+LRESULT GpuViewWin::OnMouseEvent(UINT message,
+ WPARAM wparam,
+ LPARAM lparam,
+ BOOL& handled) {
+ handled = true;
+ ::PostMessage(GetParent(), message, wparam, lparam);
+ return 0;
+}
+
+LRESULT GpuViewWin::OnKeyEvent(UINT message,
+ WPARAM wparam,
+ LPARAM lparam,
+ BOOL& handled) {
+ handled = true;
+ ::PostMessage(GetParent(), message, wparam, lparam);
+ return 0;
+}
+
+LRESULT GpuViewWin::OnWheelEvent(UINT message,
+ WPARAM wparam,
+ LPARAM lparam,
+ BOOL& handled) {
+ handled = true;
+ ::PostMessage(GetParent(), message, wparam, lparam);
+ return 0;
+}
diff --git a/chrome/gpu/gpu_view_win.h b/chrome/gpu/gpu_view_win.h
new file mode 100644
index 0000000..30efeac8
--- /dev/null
+++ b/chrome/gpu/gpu_view_win.h
@@ -0,0 +1,102 @@
+// 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_WIN_H_
+#define CHROME_GPU_GPU_VIEW_WIN_H_
+
+#include <atlbase.h>
+#include <atlapp.h>
+#include <atlcrack.h>
+#include <atlmisc.h>
+
+#include "app/gfx/native_widget_types.h"
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "ipc/ipc_channel.h"
+
+class GpuBackingStore;
+class GpuThread;
+
+namespace gfx {
+class Rect;
+class Size;
+}
+
+typedef CWinTraits<WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0>
+ GpuRenderWidgetHostViewWinTraits;
+
+class GpuViewWin
+ : public IPC::Channel::Listener,
+ public CWindowImpl<GpuViewWin,
+ CWindow,
+ GpuRenderWidgetHostViewWinTraits> {
+ public:
+ GpuViewWin(GpuThread* gpu_thread,
+ gfx::NativeViewId parent_window,
+ int32 routing_id);
+ ~GpuViewWin();
+
+ // 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);
+
+ BEGIN_MSG_MAP(GpuViewWin)
+ MSG_WM_PAINT(OnPaint)
+ MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseEvent)
+ MESSAGE_HANDLER(WM_MOUSELEAVE, OnMouseEvent)
+ MESSAGE_HANDLER(WM_LBUTTONDOWN, OnMouseEvent)
+ MESSAGE_HANDLER(WM_MBUTTONDOWN, OnMouseEvent)
+ MESSAGE_HANDLER(WM_RBUTTONDOWN, OnMouseEvent)
+ MESSAGE_HANDLER(WM_LBUTTONUP, OnMouseEvent)
+ MESSAGE_HANDLER(WM_MBUTTONUP, OnMouseEvent)
+ MESSAGE_HANDLER(WM_RBUTTONUP, OnMouseEvent)
+ MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnMouseEvent)
+ MESSAGE_HANDLER(WM_MBUTTONDBLCLK, OnMouseEvent)
+ MESSAGE_HANDLER(WM_RBUTTONDBLCLK, OnMouseEvent)
+ MESSAGE_HANDLER(WM_SYSKEYDOWN, OnKeyEvent)
+ MESSAGE_HANDLER(WM_SYSKEYUP, OnKeyEvent)
+ MESSAGE_HANDLER(WM_KEYDOWN, OnKeyEvent)
+ MESSAGE_HANDLER(WM_KEYUP, OnKeyEvent)
+ MESSAGE_HANDLER(WM_MOUSEWHEEL, OnWheelEvent)
+ MESSAGE_HANDLER(WM_MOUSEHWHEEL, OnWheelEvent)
+ MESSAGE_HANDLER(WM_HSCROLL, OnWheelEvent)
+ MESSAGE_HANDLER(WM_VSCROLL, OnWheelEvent)
+ MESSAGE_HANDLER(WM_CHAR, OnKeyEvent)
+ MESSAGE_HANDLER(WM_SYSCHAR, OnKeyEvent)
+ MESSAGE_HANDLER(WM_IME_CHAR, OnKeyEvent)
+ END_MSG_MAP()
+
+ private:
+ // IPC message handlers.
+ void OnNewBackingStore(int32 routing_id, const gfx::Size& size);
+
+ // Windows message handlers.
+ void OnPaint(HDC unused_dc);
+ LRESULT OnMouseEvent(UINT message,
+ WPARAM wparam,
+ LPARAM lparam,
+ BOOL& handled);
+ LRESULT OnKeyEvent(UINT message,
+ WPARAM wparam,
+ LPARAM lparam,
+ BOOL& handled);
+ LRESULT OnWheelEvent(UINT message,
+ WPARAM wparam,
+ LPARAM lparam,
+ BOOL& handled);
+
+ GpuThread* gpu_thread_;
+ int32 routing_id_;
+
+ HWND parent_window_;
+
+ scoped_ptr<GpuBackingStore> backing_store_;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuViewWin);
+};
+
+#endif // CHROME_GPU_GPU_VIEW_WIN_H_
diff --git a/ipc/ipc_message_utils.h b/ipc/ipc_message_utils.h
index 4f1a6f32..0bffce9 100644
--- a/ipc/ipc_message_utils.h
+++ b/ipc/ipc_message_utils.h
@@ -48,6 +48,8 @@ enum IPCMessageStart {
CommandBufferMsgStart,
UtilityMsgStart,
UtilityHostMsgStart,
+ GpuMsgStart,
+ GpuHostMsgStart,
// NOTE: When you add a new message class, also update
// IPCStatusView::IPCStatusView to ensure logging works.
LastMsgIndex