| Index: chrome/renderer/render_process.cc
|
| diff --git a/chrome/renderer/render_process.cc b/chrome/renderer/render_process.cc
|
| index 853693baf3f90a28f44f45aaa19b42f6e12e5bec..198f854ff9dc611aa15138dd524e270804b940b0 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
|
|
|