diff options
author | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-20 02:00:04 +0000 |
---|---|---|
committer | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-20 02:00:04 +0000 |
commit | e68e62fa169c45bd779bfe890aa4fcdaa24d267d (patch) | |
tree | efdb18adec880e7f780d8cde4e12893d3a20234f /chrome/renderer/render_widget.cc | |
parent | 7fe07d0726bad485fa40150aa9f7cecb1318217e (diff) | |
download | chromium_src-e68e62fa169c45bd779bfe890aa4fcdaa24d267d.zip chromium_src-e68e62fa169c45bd779bfe890aa4fcdaa24d267d.tar.gz chromium_src-e68e62fa169c45bd779bfe890aa4fcdaa24d267d.tar.bz2 |
Bitmap transport
This patch reworks bitmap transport on all platforms. Linux and Mac
are switched from serialising bitmaps over the IPC channel to using
shared memory. All platforms gain a shared memory mapping cache on the
host side.
The concept of a TransportDIB (device independent bitmap) is added to
encapsulate most of the platform specifics.
On Linux, we use SysV shared memory. This is because X shared pixmaps,
which predate POSIX SHM, can only use SysV. By using SysV between
renderer and browser, we open up the possibility to map the shared
memory directly from the renderer to the X server.
On Mac, we use POSIX shared memory. However, since this needs
filesystem access and the Mac renderer is sandboxed from the
filesystem, we add two new messages from renderer -> browser:
The first, AllocTransportDIB, synchronously creates a transport DIB in
the browser and passes a handle back to the renderer. The second,
FreeTransportDIB, asynchronously, notifies the browser that it may
close its handle to the shared memory region.
On Mac, the shared memory regions are identified by their inode
numbers on the wire. This means that the browser must keep handles
open to all the allocated shared memory regions (since an inode number
is insufficient to map the region). The alternative design is that the
renderer passes the file descriptor with each paint operation. Since
passing file descriptors is special case in the code, I felt that it
would be best to minimise their use. Creating and freeing transport
DIBs are relatively rare operations relative to paints and scrolls.
On Windows, most of the code remains the same, except that Windows now
uses the mapping cache added in this patch. This allows the browser to
maintain a shared memory mapping for a transport DIB over several
paints. Previously it mapped and unmapped for every operation, causing
lots of TLB and VM churn.
Review URL: http://codereview.chromium.org/21485
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10071 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer/render_widget.cc')
-rw-r--r-- | chrome/renderer/render_widget.cc | 76 |
1 files changed, 21 insertions, 55 deletions
diff --git a/chrome/renderer/render_widget.cc b/chrome/renderer/render_widget.cc index 04f16f1..7782fd5 100644 --- a/chrome/renderer/render_widget.cc +++ b/chrome/renderer/render_widget.cc @@ -11,6 +11,7 @@ #include "base/scoped_ptr.h" #include "build/build_config.h" #include "chrome/common/render_messages.h" +#include "chrome/common/transport_dib.h" #include "chrome/renderer/render_process.h" #include "skia/ext/platform_canvas.h" @@ -104,11 +105,11 @@ RenderWidget::RenderWidget(RenderThreadBase* render_thread, bool activatable) RenderWidget::~RenderWidget() { DCHECK(!webwidget_) << "Leaking our WebWidget!"; if (current_paint_buf_) { - RenderProcess::FreeSharedMemory(current_paint_buf_); + RenderProcess::ReleaseTransportDIB(current_paint_buf_); current_paint_buf_ = NULL; } if (current_scroll_buf_) { - RenderProcess::FreeSharedMemory(current_scroll_buf_); + RenderProcess::ReleaseTransportDIB(current_scroll_buf_); current_scroll_buf_ = NULL; } RenderProcess::ReleaseProcess(); @@ -297,20 +298,21 @@ void RenderWidget::OnPaintRectAck() { // If we sent a PaintRect message with a zero-sized bitmap, then // we should have no current paint buf. if (current_paint_buf_) { - RenderProcess::FreeSharedMemory(current_paint_buf_); + RenderProcess::ReleaseTransportDIB(current_paint_buf_); current_paint_buf_ = NULL; } + // Continue painting if necessary... DoDeferredPaint(); } void RenderWidget::OnScrollRectAck() { -#if defined(OS_WIN) DCHECK(scroll_reply_pending()); - RenderProcess::FreeSharedMemory(current_scroll_buf_); - current_scroll_buf_ = NULL; -#endif + if (current_scroll_buf_) { + RenderProcess::ReleaseTransportDIB(current_scroll_buf_); + current_scroll_buf_ = NULL; + } // Continue scrolling if necessary... DoDeferredScroll(); @@ -379,13 +381,6 @@ void RenderWidget::PaintRect(const gfx::Rect& rect, DidPaint(); } -// static -size_t RenderWidget::GetPaintBufSize(const gfx::Rect& rect) { - // TODO(darin): protect against overflow - const size_t stride = skia::PlatformCanvas::StrideForWidth(rect.width()); - return stride * rect.height(); -} - void RenderWidget::DoDeferredPaint() { if (!webwidget_ || paint_reply_pending() || paint_rect_.IsEmpty()) return; @@ -407,37 +402,23 @@ void RenderWidget::DoDeferredPaint() { paint_rect_ = gfx::Rect(); // Compute a buffer for painting and cache it. -#if defined(OS_WIN) - current_paint_buf_ = - RenderProcess::AllocSharedMemory(GetPaintBufSize(damaged_rect)); - if (!current_paint_buf_) { + skia::PlatformCanvas* canvas = + RenderProcess::GetDrawingCanvas(¤t_paint_buf_, damaged_rect); + if (!canvas) { NOTREACHED(); return; } - skia::PlatformCanvasWin canvas(damaged_rect.width(), damaged_rect.height(), - true, current_paint_buf_->handle()); -#elif defined(OS_POSIX) - // Currently, on POSIX, we are serialising the bitmap data over the IPC - // channel. - skia::PlatformCanvas canvas(damaged_rect.width(), damaged_rect.height(), - true); -#endif // defined(OS_POSIX) - PaintRect(damaged_rect, &canvas); + PaintRect(damaged_rect, canvas); ViewHostMsg_PaintRect_Params params; params.bitmap_rect = damaged_rect; params.view_size = size_; params.plugin_window_moves = plugin_window_moves_; params.flags = next_paint_flags_; + params.bitmap = current_paint_buf_->id(); -#if defined(OS_WIN) - // Windows passes a HANDLE to the shared memory over IPC - params.bitmap = current_paint_buf_->handle(); -#elif defined(OS_POSIX) - // POSIX currently passes the data itself. - params.bitmap = canvas.getDevice()->accessBitmap(false); -#endif // defined(OS_WIN) + delete canvas; plugin_window_moves_.clear(); @@ -498,21 +479,12 @@ void RenderWidget::DoDeferredScroll() { // In case the scroll offset exceeds the width/height of the scroll rect damaged_rect = scroll_rect_.Intersect(damaged_rect); -#if defined(OS_WIN) - current_scroll_buf_ = - RenderProcess::AllocSharedMemory(GetPaintBufSize(damaged_rect)); - if (!current_scroll_buf_) { + skia::PlatformCanvas* canvas = + RenderProcess::GetDrawingCanvas(¤t_scroll_buf_, damaged_rect); + if (!canvas) { NOTREACHED(); return; } - skia::PlatformCanvasWin canvas(damaged_rect.width(), damaged_rect.height(), - true, current_scroll_buf_->handle()); -#elif defined(OS_POSIX) - // Currently, on POSIX, we are serialising the bitmap data over the IPC - // channel. - skia::PlatformCanvas canvas(damaged_rect.width(), damaged_rect.height(), - true); -#endif // defined(OS_POSIX) // Set these parameters before calling Paint, since that could result in // further invalidates (uncommon). @@ -523,22 +495,16 @@ void RenderWidget::DoDeferredScroll() { params.clip_rect = scroll_rect_; params.view_size = size_; params.plugin_window_moves = plugin_window_moves_; - -#if defined(OS_WIN) - // Windows passes a HANDLE to the shared memory over IPC - params.bitmap = current_scroll_buf_->handle(); -#elif defined(OS_POSIX) - // POSIX currently passes the data itself. - params.bitmap = canvas.getDevice()->accessBitmap(false); -#endif // defined(OS_WIN) + params.bitmap = current_scroll_buf_->id(); plugin_window_moves_.clear(); // Mark the scroll operation as no longer pending. scroll_rect_ = gfx::Rect(); - PaintRect(damaged_rect, &canvas); + PaintRect(damaged_rect, canvas); Send(new ViewHostMsg_ScrollRect(routing_id_, params)); + delete canvas; UpdateIME(); } |