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 | |
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')
-rw-r--r-- | chrome/renderer/render_process.cc | 163 | ||||
-rw-r--r-- | chrome/renderer/render_process.h | 64 | ||||
-rw-r--r-- | chrome/renderer/render_process_unittest.cc | 14 | ||||
-rw-r--r-- | chrome/renderer/render_widget.cc | 76 | ||||
-rw-r--r-- | chrome/renderer/render_widget.h | 13 | ||||
-rw-r--r-- | chrome/renderer/renderer_glue.cc | 6 |
6 files changed, 185 insertions, 151 deletions
diff --git a/chrome/renderer/render_process.cc b/chrome/renderer/render_process.cc index 853693b..198f854f 100644 --- a/chrome/renderer/render_process.cc +++ b/chrome/renderer/render_process.cc @@ -25,6 +25,7 @@ #include "chrome/common/ipc_channel.h" #include "chrome/common/ipc_message_utils.h" #include "chrome/common/render_messages.h" +#include "chrome/common/transport_dib.h" #include "chrome/renderer/render_view.h" #include "webkit/glue/webkit_glue.h" @@ -36,7 +37,10 @@ bool RenderProcess::load_plugins_in_process_ = false; RenderProcess::RenderProcess(const std::wstring& channel_name) : render_thread_(channel_name), - ALLOW_THIS_IN_INITIALIZER_LIST(clearer_factory_(this)) { + ALLOW_THIS_IN_INITIALIZER_LIST(shared_mem_cache_cleaner_( + base::TimeDelta::FromSeconds(5), + this, &RenderProcess::ClearTransportDIBCache)), + sequence_number_(0) { for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) shared_mem_cache_[i] = NULL; } @@ -48,7 +52,7 @@ RenderProcess::~RenderProcess() { // This race condition causes a crash when the renderer process is shutting // down. render_thread_.Stop(); - ClearSharedMemCache(); + ClearTransportDIBCache(); } // static @@ -124,97 +128,144 @@ bool RenderProcess::ShouldLoadPluginsInProcess() { return load_plugins_in_process_; } -// static -base::SharedMemory* RenderProcess::AllocSharedMemory(size_t size) { - self()->clearer_factory_.RevokeAll(); - - base::SharedMemory* mem = self()->GetSharedMemFromCache(size); - if (mem) - return mem; +// ----------------------------------------------------------------------------- +// Platform specific code for dealing with bitmap transport... - // Round-up size to allocation granularity - size_t allocation_granularity = base::SysInfo::VMAllocationGranularity(); - size = size / allocation_granularity + 1; - size = size * allocation_granularity; +// ----------------------------------------------------------------------------- +// Create a platform canvas object which renders into the given transport +// memory. +// ----------------------------------------------------------------------------- +static skia::PlatformCanvas* CanvasFromTransportDIB( + TransportDIB* dib, const gfx::Rect& rect) { +#if defined(OS_WIN) + return new skia::PlatformCanvas(rect.width(), rect.height(), true, + dib->handle()); +#elif defined(OS_LINUX) || defined(OS_MACOSX) + return new skia::PlatformCanvas(rect.width(), rect.height(), true, + reinterpret_cast<uint8_t*>(dib->memory())); +#endif +} - mem = new base::SharedMemory(); - if (!mem) +TransportDIB* RenderProcess::CreateTransportDIB(size_t size) { +#if defined(OS_WIN) || defined(OS_LINUX) + // Windows and Linux create transport DIBs inside the renderer + return TransportDIB::Create(size, sequence_number_++); +#elif defined(OS_MACOSX) // defined(OS_WIN) || defined(OS_LINUX) + // Mac creates transport DIBs in the browser, so we need to do a sync IPC to + // get one. + IPC::Maybe<TransportDIB::Handle> mhandle; + IPC::Message* msg = new ViewHostMsg_AllocTransportDIB(size, &mhandle); + if (!render_thread_.Send(msg)) return NULL; - if (!mem->Create(L"", false, true, size)) { - delete mem; + if (!mhandle.valid) return NULL; + return TransportDIB::Map(mhandle.value); +#endif // defined(OS_MACOSX) +} + +void RenderProcess::FreeTransportDIB(TransportDIB* dib) { + if (!dib) + return; + +#if defined(OS_MACOSX) + // On Mac we need to tell the browser that it can drop a reference to the + // shared memory. + IPC::Message* msg = new ViewHostMsg_FreeTransportDIB(dib->id()); + render_thread_.Send(msg); +#endif + + delete dib; +} + +// ----------------------------------------------------------------------------- + + +// static +skia::PlatformCanvas* RenderProcess::GetDrawingCanvas( + TransportDIB** memory, const gfx::Rect& rect) { + const size_t stride = skia::PlatformCanvas::StrideForWidth(rect.width()); + const size_t size = stride * rect.height(); + + if (!self()->GetTransportDIBFromCache(memory, size)) { + *memory = self()->CreateTransportDIB(size); + if (!*memory) + return false; } - return mem; + return CanvasFromTransportDIB(*memory, rect); } // static -void RenderProcess::FreeSharedMemory(base::SharedMemory* mem) { +void RenderProcess::ReleaseTransportDIB(TransportDIB* mem) { if (self()->PutSharedMemInCache(mem)) { - self()->ScheduleCacheClearer(); + self()->shared_mem_cache_cleaner_.Reset(); return; } - DeleteSharedMem(mem); -} -// static -void RenderProcess::DeleteSharedMem(base::SharedMemory* mem) { - delete mem; + self()->FreeTransportDIB(mem); } -base::SharedMemory* RenderProcess::GetSharedMemFromCache(size_t size) { +bool RenderProcess::GetTransportDIBFromCache(TransportDIB** mem, + size_t size) { // look for a cached object that is suitable for the requested size. for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) { - base::SharedMemory* mem = shared_mem_cache_[i]; - if (mem && mem->max_size() >= size) { + if (shared_mem_cache_[i] && + size <= shared_mem_cache_[i]->size()) { + *mem = shared_mem_cache_[i]; shared_mem_cache_[i] = NULL; - return mem; + return true; } } - return NULL; + + return false; } -bool RenderProcess::PutSharedMemInCache(base::SharedMemory* mem) { +int RenderProcess::FindFreeCacheSlot(size_t size) { // simple algorithm: // - look for an empty slot to store mem, or - // - if full, then replace any existing cache entry that is smaller than the - // given shared memory object. + // - if full, then replace smallest entry which is smaller than |size| for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) { - if (!shared_mem_cache_[i]) { - shared_mem_cache_[i] = mem; - return true; - } + if (shared_mem_cache_[i] == NULL) + return i; } - for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) { - base::SharedMemory* cached_mem = shared_mem_cache_[i]; - if (cached_mem->max_size() < mem->max_size()) { - shared_mem_cache_[i] = mem; - DeleteSharedMem(cached_mem); - return true; + + size_t smallest_size = size; + int smallest_index = -1; + + for (size_t i = 1; i < arraysize(shared_mem_cache_); ++i) { + const size_t entry_size = shared_mem_cache_[i]->size(); + if (entry_size < smallest_size) { + smallest_size = entry_size; + smallest_index = i; } } - return false; + + if (smallest_index != -1) { + FreeTransportDIB(shared_mem_cache_[smallest_index]); + shared_mem_cache_[smallest_index] = NULL; + } + + return smallest_index; } -void RenderProcess::ClearSharedMemCache() { +bool RenderProcess::PutSharedMemInCache(TransportDIB* mem) { + const int slot = FindFreeCacheSlot(mem->size()); + if (slot == -1) + return false; + + shared_mem_cache_[slot] = mem; + return true; +} + +void RenderProcess::ClearTransportDIBCache() { for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) { if (shared_mem_cache_[i]) { - DeleteSharedMem(shared_mem_cache_[i]); + FreeTransportDIB(shared_mem_cache_[i]); shared_mem_cache_[i] = NULL; } } } -void RenderProcess::ScheduleCacheClearer() { - // If we already have a deferred clearer, then revoke it so we effectively - // delay cache clearing until idle for our desired interval. - clearer_factory_.RevokeAll(); - - MessageLoop::current()->PostDelayedTask(FROM_HERE, - clearer_factory_.NewRunnableMethod(&RenderProcess::ClearSharedMemCache), - 5000 /* 5 seconds */); -} - void RenderProcess::Cleanup() { // TODO(port) // Try and limit what we pull in for our non-Win unit test bundle diff --git a/chrome/renderer/render_process.h b/chrome/renderer/render_process.h index 6ba0905..9c4cabe 100644 --- a/chrome/renderer/render_process.h +++ b/chrome/renderer/render_process.h @@ -5,13 +5,17 @@ #ifndef CHROME_RENDERER_RENDER_PROCESS_H__ #define CHROME_RENDERER_RENDER_PROCESS_H__ +#include "base/timer.h" #include "chrome/common/child_process.h" #include "chrome/renderer/render_thread.h" +#include "skia/ext/platform_canvas.h" -namespace base { - class SharedMemory; +namespace gfx { +class Rect; } +class TransportDIB; + // Represents the renderer end of the browser<->renderer connection. The // opposite end is the RenderProcessHost. This is a singleton object for // each renderer. @@ -23,19 +27,19 @@ class RenderProcess : public ChildProcess { // Returns true if plugins should be loaded in-process. static bool ShouldLoadPluginsInProcess(); - // Allocates shared memory. When no longer needed, you should pass the - // SharedMemory pointer to FreeSharedMemory so it can be recycled. The size - // reported in the resulting SharedMemory object will be greater than or - // equal to the requested size. This method returns NULL if unable to - // allocate memory for some reason. - static base::SharedMemory* AllocSharedMemory(size_t size); + // Get a canvas suitable for drawing and transporting to the browser + // memory: (output) the transport DIB memory + // rect: the rectangle which will be painted, use for sizing the canvas + // returns: NULL on error + // + // When no longer needed, you should pass the TransportDIB to + // ReleaseTransportDIB so that it can be recycled. + static skia::PlatformCanvas* GetDrawingCanvas( + TransportDIB** memory, const gfx::Rect& rect); // Frees shared memory allocated by AllocSharedMemory. You should only use // this function to free the SharedMemory object. - static void FreeSharedMemory(base::SharedMemory* mem); - - // Deletes the shared memory allocated by AllocSharedMemory. - static void DeleteSharedMem(base::SharedMemory* mem); + static void ReleaseTransportDIB(TransportDIB* memory); private: friend class ChildProcessFactory<RenderProcess>; @@ -50,21 +54,28 @@ class RenderProcess : public ChildProcess { static ChildProcess* ClassFactory(const std::wstring& channel_name); - // Look in the shared memory cache for a suitable object to reuse. Returns - // NULL if there is none. - base::SharedMemory* GetSharedMemFromCache(size_t size); + // Look in the shared memory cache for a suitable object to reuse. + // result: (output) the memory found + // size: the resulting memory will be >= this size, in bytes + // returns: false if a suitable DIB memory could not be found + bool GetTransportDIBFromCache(TransportDIB** result, size_t size); - // Maybe put the given shared memory into the shared memory cache. Returns + // Maybe put the given shared memory into the shared memory cache. Returns // true if the SharedMemory object was stored in the cache; otherwise, false // is returned. - bool PutSharedMemInCache(base::SharedMemory* mem); + bool PutSharedMemInCache(TransportDIB* memory); - void ClearSharedMemCache(); + void ClearTransportDIBCache(); - // We want to lazily clear the shared memory cache if no one has requested - // memory. This methods are used to schedule a deferred call to - // RenderProcess::ClearSharedMemCache. - void ScheduleCacheClearer(); + // Return the index of a free cache slot in which to install a transport DIB + // of the given size. If all entries in the cache are larger than the given + // size, this doesn't free any slots and returns -1. + int FindFreeCacheSlot(size_t size); + + // Create a new transport DIB of, at least, the given size. Return NULL on + // error. + TransportDIB* CreateTransportDIB(size_t size); + void FreeTransportDIB(TransportDIB*); // ChildProcess implementation virtual void Cleanup(); @@ -74,10 +85,13 @@ class RenderProcess : public ChildProcess { // A very simplistic and small cache. If an entry in this array is non-null, // then it points to a SharedMemory object that is available for reuse. - base::SharedMemory* shared_mem_cache_[2]; + TransportDIB* shared_mem_cache_[2]; + + // This DelayTimer cleans up our cache 5 seconds after the last use. + base::DelayTimer<RenderProcess> shared_mem_cache_cleaner_; - // This factory is used to lazily invoke ClearSharedMemCache. - ScopedRunnableMethodFactory<RenderProcess> clearer_factory_; + // TransportDIB sequence number + uint32 sequence_number_; static bool load_plugins_in_process_; diff --git a/chrome/renderer/render_process_unittest.cc b/chrome/renderer/render_process_unittest.cc index 0303d40..7b7b7c6 100644 --- a/chrome/renderer/render_process_unittest.cc +++ b/chrome/renderer/render_process_unittest.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/gfx/rect.h" #include "base/sys_info.h" #include "base/string_util.h" #include "chrome/renderer/render_process.h" @@ -24,11 +25,14 @@ class RenderProcessTest : public testing::Test { }; -TEST_F(RenderProcessTest, TestSharedMemoryAllocOne) { - size_t size = base::SysInfo::VMAllocationGranularity(); - base::SharedMemory* mem = RenderProcess::AllocSharedMemory(size); - ASSERT_TRUE(mem); - RenderProcess::FreeSharedMemory(mem); +TEST_F(RenderProcessTest, TestTransportDIBAllocation) { + const gfx::Rect rect(0, 0, 100, 100); + TransportDIB* dib; + skia::PlatformCanvas* canvas = RenderProcess::GetDrawingCanvas(&dib, rect); + ASSERT_TRUE(dib); + ASSERT_TRUE(canvas); + RenderProcess::ReleaseTransportDIB(dib); + delete canvas; } } // namespace 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(); } diff --git a/chrome/renderer/render_widget.h b/chrome/renderer/render_widget.h index 4153ce0..b0c4b11 100644 --- a/chrome/renderer/render_widget.h +++ b/chrome/renderer/render_widget.h @@ -14,6 +14,7 @@ #include "base/ref_counted.h" #include "base/shared_memory.h" #include "chrome/common/ipc_channel.h" +#include "chrome/renderer/render_process.h" #include "skia/ext/platform_canvas.h" #include "webkit/glue/webwidget_delegate.h" @@ -86,10 +87,6 @@ class RenderWidget : public IPC::Channel::Listener, // Close the underlying WebWidget. void Close(); - // Get the size of the paint buffer for the given rectangle, rounding up to - // the allocation granularity of the system. - static size_t GetPaintBufSize(const gfx::Rect& rect); - protected: // Friend RefCounted so that the dtor can be non-public. Using this class // without ref-counting is an error. @@ -192,10 +189,10 @@ class RenderWidget : public IPC::Channel::Listener, // The size of the RenderWidget. gfx::Size size_; - // Shared memory handles that are currently in use to transfer an image to - // the browser. - base::SharedMemory* current_paint_buf_; - base::SharedMemory* current_scroll_buf_; + // Transport DIBs that are currently in use to transfer an image to the + // browser. + TransportDIB* current_paint_buf_; + TransportDIB* current_scroll_buf_; // The smallest bounding rectangle that needs to be re-painted. This is non- // empty if a paint event is pending. diff --git a/chrome/renderer/renderer_glue.cc b/chrome/renderer/renderer_glue.cc index a8a9486..a65f326 100644 --- a/chrome/renderer/renderer_glue.cc +++ b/chrome/renderer/renderer_glue.cc @@ -95,7 +95,9 @@ void ScopedClipboardWriterGlue::WriteBitmap(const SkBitmap& bitmap) { gfx::Size size(bitmap.width(), bitmap.height()); // Allocate a shared memory buffer to hold the bitmap bits - shared_buf_ = RenderProcess::AllocSharedMemory(buf_size); + shared_buf_ = new base::SharedMemory; + shared_buf_->Create(L"", false /* read write */, true /* open existing */, + buf_size); if (!shared_buf_ || !shared_buf_->Map(buf_size)) { NOTREACHED(); return; @@ -134,7 +136,7 @@ ScopedClipboardWriterGlue::~ScopedClipboardWriterGlue() { if (shared_buf_) { g_render_thread->Send( new ViewHostMsg_ClipboardWriteObjectsSync(objects_)); - RenderProcess::FreeSharedMemory(shared_buf_); + delete shared_buf_; return; } #endif |