Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1985)

Unified Diff: chrome/renderer/render_process.cc

Issue 21485: Bitmap transport (Closed)
Patch Set: Fix some mac crashes Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698