summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjbauman@chromium.org <jbauman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-14 21:50:36 +0000
committerjbauman@chromium.org <jbauman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-14 21:50:36 +0000
commit142b19f13984918a79842905ddfee6efed72e56d (patch)
tree7efe121e525119596cbe23fdc6b12120b43c6ae5
parent6b4c88b9d8dc0dbcca025bd768dd62dce09d362a (diff)
downloadchromium_src-142b19f13984918a79842905ddfee6efed72e56d.zip
chromium_src-142b19f13984918a79842905ddfee6efed72e56d.tar.gz
chromium_src-142b19f13984918a79842905ddfee6efed72e56d.tar.bz2
Revert 257161 "Revert 256955 "Add shared bitmap managers for bro..."
Turns out the child process was mapping the memory twice, so fixed that. > Revert 256955 "Add shared bitmap managers for browser and render..." > > Seems to be causing renderer crashes and possibly out-of-memory issues. > > > Add shared bitmap managers for browser and renderer processes. > > > > The shared bitmap managers will allow software tiles to be allocated in shared memory, so delegated rendering could be used with them. > > > > BUG=327220 > > R=danakj@chromium.org, jschuh@chromium.org, piman@chromium.org > > > > Review URL: https://codereview.chromium.org/148243013 > > TBR=jbauman@chromium.org > > Review URL: https://codereview.chromium.org/197703004 TBR=jbauman@chromium.org Review URL: https://codereview.chromium.org/200913002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@257216 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--cc/output/delegating_renderer.cc4
-rw-r--r--cc/resources/resource_provider.cc3
-rw-r--r--cc/resources/shared_bitmap.cc25
-rw-r--r--cc/resources/shared_bitmap.h6
-rw-r--r--content/browser/compositor/image_transport_factory.cc2
-rw-r--r--content/browser/renderer_host/render_message_filter.cc28
-rw-r--r--content/browser/renderer_host/render_message_filter.h8
-rw-r--r--content/child/child_shared_bitmap_manager.cc91
-rw-r--r--content/child/child_shared_bitmap_manager.h40
-rw-r--r--content/child/child_thread.cc4
-rw-r--r--content/child/child_thread.h7
-rw-r--r--content/common/child_process_messages.h18
-rw-r--r--content/common/host_shared_bitmap_manager.cc168
-rw-r--r--content/common/host_shared_bitmap_manager.h82
-rw-r--r--content/common/host_shared_bitmap_manager_unittest.cc160
-rw-r--r--content/content_child.gypi2
-rw-r--r--content/content_common.gypi2
-rw-r--r--content/content_tests.gypi1
-rw-r--r--content/renderer/gpu/render_widget_compositor.cc8
-rw-r--r--ui/compositor/compositor.cc14
-rw-r--r--ui/compositor/compositor.h2
21 files changed, 668 insertions, 7 deletions
diff --git a/cc/output/delegating_renderer.cc b/cc/output/delegating_renderer.cc
index 66cd53c..b189386 100644
--- a/cc/output/delegating_renderer.cc
+++ b/cc/output/delegating_renderer.cc
@@ -162,8 +162,8 @@ void DelegatingRenderer::SetVisible(bool visible) {
// We loop visibility to the GPU process, since that's what manages memory.
// That will allow it to feed us with memory allocations that we can act
// upon.
- DCHECK(context_provider);
- context_provider->ContextSupport()->SetSurfaceVisible(visible);
+ if (context_provider)
+ context_provider->ContextSupport()->SetSurfaceVisible(visible);
}
void DelegatingRenderer::SendManagedMemoryStats(size_t bytes_visible,
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc
index ed1d0da..2fee3d2 100644
--- a/cc/resources/resource_provider.cc
+++ b/cc/resources/resource_provider.cc
@@ -1949,7 +1949,8 @@ void ResourceProvider::BeginSetPixels(ResourceId id) {
DCHECK(resource->pixel_buffer);
DCHECK_EQ(RGBA_8888, resource->format);
- std::swap(resource->pixels, resource->pixel_buffer);
+ memcpy(
+ resource->pixels, resource->pixel_buffer, 4 * resource->size.GetArea());
delete[] resource->pixel_buffer;
resource->pixel_buffer = NULL;
}
diff --git a/cc/resources/shared_bitmap.cc b/cc/resources/shared_bitmap.cc
index 3a6fc35..3b94d45 100644
--- a/cc/resources/shared_bitmap.cc
+++ b/cc/resources/shared_bitmap.cc
@@ -4,6 +4,9 @@
#include "cc/resources/shared_bitmap.h"
+#include "base/numerics/safe_math.h"
+#include "base/rand_util.h"
+
namespace cc {
SharedBitmap::SharedBitmap(
@@ -14,4 +17,26 @@ SharedBitmap::SharedBitmap(
SharedBitmap::~SharedBitmap() { free_callback_.Run(this); }
+// static
+bool SharedBitmap::GetSizeInBytes(const gfx::Size& size,
+ size_t* size_in_bytes) {
+ if (size.width() <= 0 || size.height() <= 0)
+ return false;
+ base::CheckedNumeric<int> s = size.width();
+ s *= size.height();
+ s *= 4;
+ if (!s.IsValid())
+ return false;
+ *size_in_bytes = s.ValueOrDie();
+ return true;
+}
+
+// static
+SharedBitmapId SharedBitmap::GenerateId() {
+ SharedBitmapId id;
+ // Needs cryptographically-secure random numbers.
+ base::RandBytes(id.name, sizeof(id.name));
+ return id;
+}
+
} // namespace cc
diff --git a/cc/resources/shared_bitmap.h b/cc/resources/shared_bitmap.h
index 9575068..d62ffcc 100644
--- a/cc/resources/shared_bitmap.h
+++ b/cc/resources/shared_bitmap.h
@@ -10,6 +10,7 @@
#include "base/memory/shared_memory.h"
#include "cc/base/cc_export.h"
#include "gpu/command_buffer/common/mailbox.h"
+#include "ui/gfx/size.h"
namespace base { class SharedMemory; }
@@ -38,6 +39,11 @@ class CC_EXPORT SharedBitmap {
SharedBitmapId id() { return id_; }
+ // Returns true if the size is valid and false otherwise.
+ static bool GetSizeInBytes(const gfx::Size& size, size_t* size_in_bytes);
+
+ static SharedBitmapId GenerateId();
+
private:
base::SharedMemory* memory_;
SharedBitmapId id_;
diff --git a/content/browser/compositor/image_transport_factory.cc b/content/browser/compositor/image_transport_factory.cc
index c0b739d..70ffc9c 100644
--- a/content/browser/compositor/image_transport_factory.cc
+++ b/content/browser/compositor/image_transport_factory.cc
@@ -7,6 +7,7 @@
#include "base/command_line.h"
#include "content/browser/compositor/gpu_process_transport_factory.h"
#include "content/browser/compositor/no_transport_image_transport_factory.h"
+#include "content/common/host_shared_bitmap_manager.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/compositor_switches.h"
#include "ui/gl/gl_implementation.h"
@@ -26,6 +27,7 @@ void ImageTransportFactory::Initialize() {
return;
g_factory = new GpuProcessTransportFactory;
ui::ContextFactory::SetInstance(g_factory->AsContextFactory());
+ ui::Compositor::SetSharedBitmapManager(HostSharedBitmapManager::current());
}
void ImageTransportFactory::InitializeForUnitTests(
diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc
index 0aa002b..958b491 100644
--- a/content/browser/renderer_host/render_message_filter.cc
+++ b/content/browser/renderer_host/render_message_filter.cc
@@ -35,6 +35,7 @@
#include "content/common/desktop_notification_messages.h"
#include "content/common/frame_messages.h"
#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
+#include "content/common/host_shared_bitmap_manager.h"
#include "content/common/media/media_param_traits.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_child_process_host.h"
@@ -354,6 +355,7 @@ RenderMessageFilter::~RenderMessageFilter() {
}
void RenderMessageFilter::OnChannelClosing() {
+ HostSharedBitmapManager::current()->ProcessRemoved(PeerHandle());
#if defined(ENABLE_PLUGINS)
for (std::set<OpenChannelToNpapiPluginCallback*>::iterator it =
plugin_host_clients_.begin(); it != plugin_host_clients_.end(); ++it) {
@@ -430,8 +432,14 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message,
OnCheckNotificationPermission)
IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateSharedMemory,
OnAllocateSharedMemory)
+ IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateSharedBitmap,
+ OnAllocateSharedBitmap)
IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer,
OnAllocateGpuMemoryBuffer)
+ IPC_MESSAGE_HANDLER(ChildProcessHostMsg_AllocatedSharedBitmap,
+ OnAllocatedSharedBitmap)
+ IPC_MESSAGE_HANDLER(ChildProcessHostMsg_DeletedSharedBitmap,
+ OnDeletedSharedBitmap)
#if defined(OS_POSIX) && !defined(TOOLKIT_GTK) && !defined(OS_ANDROID)
IPC_MESSAGE_HANDLER(ViewHostMsg_AllocTransportDIB, OnAllocTransportDIB)
IPC_MESSAGE_HANDLER(ViewHostMsg_FreeTransportDIB, OnFreeTransportDIB)
@@ -926,6 +934,26 @@ void RenderMessageFilter::OnAllocateSharedMemory(
buffer_size, PeerHandle(), handle);
}
+void RenderMessageFilter::OnAllocateSharedBitmap(
+ uint32 buffer_size,
+ const cc::SharedBitmapId& id,
+ base::SharedMemoryHandle* handle) {
+ HostSharedBitmapManager::current()->AllocateSharedBitmapForChild(
+ PeerHandle(), buffer_size, id, handle);
+}
+
+void RenderMessageFilter::OnAllocatedSharedBitmap(
+ size_t buffer_size,
+ const base::SharedMemoryHandle& handle,
+ const cc::SharedBitmapId& id) {
+ HostSharedBitmapManager::current()->ChildAllocatedSharedBitmap(
+ buffer_size, handle, PeerHandle(), id);
+}
+
+void RenderMessageFilter::OnDeletedSharedBitmap(const cc::SharedBitmapId& id) {
+ HostSharedBitmapManager::current()->ChildDeletedSharedBitmap(id);
+}
+
net::CookieStore* RenderMessageFilter::GetCookieStoreForURL(
const GURL& url) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
diff --git a/content/browser/renderer_host/render_message_filter.h b/content/browser/renderer_host/render_message_filter.h
index b87b962..a82ed94 100644
--- a/content/browser/renderer_host/render_message_filter.h
+++ b/content/browser/renderer_host/render_message_filter.h
@@ -19,6 +19,7 @@
#include "base/sequenced_task_runner_helpers.h"
#include "base/strings/string16.h"
#include "build/build_config.h"
+#include "cc/resources/shared_bitmap_manager.h"
#include "content/common/pepper_renderer_instance_data.h"
#include "content/public/browser/browser_message_filter.h"
#include "content/public/common/three_d_api_types.h"
@@ -213,6 +214,13 @@ class RenderMessageFilter : public BrowserMessageFilter {
// in the renderer on POSIX due to the sandbox.
void OnAllocateSharedMemory(uint32 buffer_size,
base::SharedMemoryHandle* handle);
+ void OnAllocateSharedBitmap(uint32 buffer_size,
+ const cc::SharedBitmapId& id,
+ base::SharedMemoryHandle* handle);
+ void OnAllocatedSharedBitmap(size_t buffer_size,
+ const base::SharedMemoryHandle& handle,
+ const cc::SharedBitmapId& id);
+ void OnDeletedSharedBitmap(const cc::SharedBitmapId& id);
void OnResolveProxy(const GURL& url, IPC::Message* reply_msg);
// Browser side transport DIB allocation
diff --git a/content/child/child_shared_bitmap_manager.cc b/content/child/child_shared_bitmap_manager.cc
new file mode 100644
index 0000000..7325789
--- /dev/null
+++ b/content/child/child_shared_bitmap_manager.cc
@@ -0,0 +1,91 @@
+// Copyright (c) 2013 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 "content/child/child_shared_bitmap_manager.h"
+
+#include "content/child/child_thread.h"
+#include "content/common/child_process_messages.h"
+#include "ui/gfx/size.h"
+
+namespace content {
+
+ChildSharedBitmapManager::ChildSharedBitmapManager(
+ scoped_refptr<ThreadSafeSender> sender)
+ : sender_(sender) {}
+
+ChildSharedBitmapManager::~ChildSharedBitmapManager() {}
+
+scoped_ptr<cc::SharedBitmap> ChildSharedBitmapManager::AllocateSharedBitmap(
+ const gfx::Size& size) {
+ TRACE_EVENT2("renderer",
+ "ChildSharedBitmapManager::AllocateSharedMemory",
+ "width",
+ size.width(),
+ "height",
+ size.height());
+ size_t memory_size;
+ if (!cc::SharedBitmap::GetSizeInBytes(size, &memory_size))
+ return scoped_ptr<cc::SharedBitmap>();
+ cc::SharedBitmapId id = cc::SharedBitmap::GenerateId();
+ scoped_ptr<base::SharedMemory> memory;
+#if defined(OS_POSIX)
+ base::SharedMemoryHandle handle;
+ sender_->Send(new ChildProcessHostMsg_SyncAllocateSharedBitmap(
+ memory_size, id, &handle));
+ memory = make_scoped_ptr(new base::SharedMemory(handle, false));
+ memory->Map(memory_size);
+#else
+ memory.reset(ChildThread::AllocateSharedMemory(memory_size, sender_));
+ CHECK(memory);
+ base::SharedMemoryHandle handle_to_send = memory->handle();
+ sender_->Send(new ChildProcessHostMsg_AllocatedSharedBitmap(
+ memory_size, handle_to_send, id));
+#endif
+ // The compositor owning the SharedBitmap will be closed before the
+ // ChildThread containng this, making the use of base::Unretained safe.
+ return scoped_ptr<cc::SharedBitmap>(new cc::SharedBitmap(
+ memory.release(),
+ id,
+ base::Bind(&ChildSharedBitmapManager::FreeSharedMemory,
+ base::Unretained(this))));
+}
+
+scoped_ptr<cc::SharedBitmap> ChildSharedBitmapManager::GetSharedBitmapFromId(
+ const gfx::Size&,
+ const cc::SharedBitmapId&) {
+ NOTREACHED();
+ return scoped_ptr<cc::SharedBitmap>();
+}
+
+scoped_ptr<cc::SharedBitmap> ChildSharedBitmapManager::GetBitmapForSharedMemory(
+ base::SharedMemory* mem) {
+ cc::SharedBitmapId id = cc::SharedBitmap::GenerateId();
+ base::SharedMemoryHandle handle_to_send = mem->handle();
+#if defined(OS_POSIX)
+ if (!mem->ShareToProcess(base::GetCurrentProcessHandle(), &handle_to_send))
+ return scoped_ptr<cc::SharedBitmap>();
+#endif
+ sender_->Send(new ChildProcessHostMsg_AllocatedSharedBitmap(
+ mem->mapped_size(), handle_to_send, id));
+ // The compositor owning the SharedBitmap will be closed before the
+ // ChildThread containng this, making the use of base::Unretained safe.
+ return scoped_ptr<cc::SharedBitmap>(new cc::SharedBitmap(
+ mem,
+ id,
+ base::Bind(&ChildSharedBitmapManager::ReleaseSharedBitmap,
+ base::Unretained(this))));
+}
+
+void ChildSharedBitmapManager::FreeSharedMemory(cc::SharedBitmap* bitmap) {
+ TRACE_EVENT0("renderer", "ChildSharedBitmapManager::FreeSharedMemory");
+ sender_->Send(new ChildProcessHostMsg_DeletedSharedBitmap(bitmap->id()));
+ delete bitmap->memory();
+}
+
+void ChildSharedBitmapManager::ReleaseSharedBitmap(cc::SharedBitmap* handle) {
+ TRACE_EVENT0("renderer", "ChildSharedBitmapManager::ReleaseSharedBitmap");
+ sender_->Send(new ChildProcessHostMsg_DeletedSharedBitmap(handle->id()));
+}
+
+} // namespace content
diff --git a/content/child/child_shared_bitmap_manager.h b/content/child/child_shared_bitmap_manager.h
new file mode 100644
index 0000000..1e54466
--- /dev/null
+++ b/content/child/child_shared_bitmap_manager.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2013 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 CONTENT_CHILD_CHILD_SHARED_BITMAP_MANAGER_H_
+#define CONTENT_CHILD_CHILD_SHARED_BITMAP_MANAGER_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/shared_memory.h"
+#include "cc/resources/shared_bitmap_manager.h"
+#include "content/child/thread_safe_sender.h"
+
+namespace content {
+
+class ChildSharedBitmapManager : public cc::SharedBitmapManager {
+ public:
+ ChildSharedBitmapManager(scoped_refptr<ThreadSafeSender> sender);
+ virtual ~ChildSharedBitmapManager();
+
+ virtual scoped_ptr<cc::SharedBitmap> AllocateSharedBitmap(
+ const gfx::Size& size) OVERRIDE;
+ virtual scoped_ptr<cc::SharedBitmap> GetSharedBitmapFromId(
+ const gfx::Size&,
+ const cc::SharedBitmapId&) OVERRIDE;
+ virtual scoped_ptr<cc::SharedBitmap> GetBitmapForSharedMemory(
+ base::SharedMemory* mem) OVERRIDE;
+
+ private:
+ void FreeSharedMemory(cc::SharedBitmap* bitmap);
+ void ReleaseSharedBitmap(cc::SharedBitmap*);
+
+ scoped_refptr<ThreadSafeSender> sender_;
+
+ DISALLOW_COPY_AND_ASSIGN(ChildSharedBitmapManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_CHILD_SHARED_BITMAP_MANAGER_H_
diff --git a/content/child/child_thread.cc b/content/child/child_thread.cc
index 57919e5..3ecdb58 100644
--- a/content/child/child_thread.cc
+++ b/content/child/child_thread.cc
@@ -27,6 +27,7 @@
#include "content/child/child_histogram_message_filter.h"
#include "content/child/child_process.h"
#include "content/child/child_resource_message_filter.h"
+#include "content/child/child_shared_bitmap_manager.h"
#include "content/child/fileapi/file_system_dispatcher.h"
#include "content/child/power_monitor_broadcast_source.h"
#include "content/child/quota_dispatcher.h"
@@ -311,6 +312,9 @@ void ChildThread::Init() {
::HeapProfilerStop,
::GetHeapProfile));
#endif
+
+ shared_bitmap_manager_.reset(
+ new ChildSharedBitmapManager(thread_safe_sender()));
}
ChildThread::~ChildThread() {
diff --git a/content/child/child_thread.h b/content/child/child_thread.h
index 33083bf..233e9c8 100644
--- a/content/child/child_thread.h
+++ b/content/child/child_thread.h
@@ -38,6 +38,7 @@ class WebFrame;
namespace content {
class ChildHistogramMessageFilter;
class ChildResourceMessageFilter;
+class ChildSharedBitmapManager;
class FileSystemDispatcher;
class ServiceWorkerDispatcher;
class ServiceWorkerMessageFilter;
@@ -86,6 +87,10 @@ class CONTENT_EXPORT ChildThread : public IPC::Listener, public IPC::Sender {
static base::SharedMemory* AllocateSharedMemory(size_t buf_size,
IPC::Sender* sender);
+ ChildSharedBitmapManager* shared_bitmap_manager() const {
+ return shared_bitmap_manager_.get();
+ }
+
ResourceDispatcher* resource_dispatcher() const {
return resource_dispatcher_.get();
}
@@ -227,6 +232,8 @@ class CONTENT_EXPORT ChildThread : public IPC::Listener, public IPC::Sender {
scoped_refptr<QuotaMessageFilter> quota_message_filter_;
+ scoped_ptr<ChildSharedBitmapManager> shared_bitmap_manager_;
+
base::WeakPtrFactory<ChildThread> channel_connected_factory_;
// Observes the trace event system. When tracing is enabled, optionally
diff --git a/content/common/child_process_messages.h b/content/common/child_process_messages.h
index 5700c48..f220891 100644
--- a/content/common/child_process_messages.h
+++ b/content/common/child_process_messages.h
@@ -11,6 +11,7 @@
#include "base/memory/shared_memory.h"
#include "base/tracked_objects.h"
#include "base/values.h"
+#include "cc/resources/shared_bitmap_manager.h"
#include "content/common/content_export.h"
#include "ipc/ipc_message_macros.h"
#include "ui/gfx/gpu_memory_buffer.h"
@@ -146,6 +147,23 @@ IPC_SYNC_MESSAGE_CONTROL1_1(ChildProcessHostMsg_SyncAllocateSharedMemory,
uint32 /* buffer size */,
base::SharedMemoryHandle)
+// Asks the browser to create a block of shared memory for the child process to
+// fill in and pass back to the browser.
+IPC_SYNC_MESSAGE_CONTROL2_1(ChildProcessHostMsg_SyncAllocateSharedBitmap,
+ uint32 /* buffer size */,
+ cc::SharedBitmapId,
+ base::SharedMemoryHandle)
+
+// Informs the browser that the child allocated a shared bitmap.
+IPC_MESSAGE_CONTROL3(ChildProcessHostMsg_AllocatedSharedBitmap,
+ uint32 /* buffer size */,
+ base::SharedMemoryHandle,
+ cc::SharedBitmapId)
+
+// Informs the browser that the child deleted a shared bitmap.
+IPC_MESSAGE_CONTROL1(ChildProcessHostMsg_DeletedSharedBitmap,
+ cc::SharedBitmapId)
+
#if defined(USE_TCMALLOC)
// Reply to ChildProcessMsg_GetTcmallocStats.
IPC_MESSAGE_CONTROL1(ChildProcessHostMsg_TcmallocStats,
diff --git a/content/common/host_shared_bitmap_manager.cc b/content/common/host_shared_bitmap_manager.cc
new file mode 100644
index 0000000..aa0cd81
--- /dev/null
+++ b/content/common/host_shared_bitmap_manager.cc
@@ -0,0 +1,168 @@
+// Copyright 2013 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 "content/common/host_shared_bitmap_manager.h"
+
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "content/common/view_messages.h"
+#include "ui/gfx/size.h"
+
+namespace content {
+
+class BitmapData : public base::RefCountedThreadSafe<BitmapData> {
+ public:
+ BitmapData(base::ProcessHandle process_handle,
+ base::SharedMemoryHandle memory_handle,
+ size_t buffer_size)
+ : process_handle(process_handle),
+ memory_handle(memory_handle),
+ buffer_size(buffer_size) {}
+ base::ProcessHandle process_handle;
+ base::SharedMemoryHandle memory_handle;
+ scoped_ptr<base::SharedMemory> memory;
+ size_t buffer_size;
+
+ private:
+ friend class base::RefCountedThreadSafe<BitmapData>;
+ ~BitmapData() {}
+ DISALLOW_COPY_AND_ASSIGN(BitmapData);
+};
+
+// Holds a reference on the memory to keep it alive.
+void FreeSharedMemory(scoped_refptr<BitmapData> data,
+ cc::SharedBitmap* bitmap) {}
+
+base::LazyInstance<HostSharedBitmapManager> g_shared_memory_manager =
+ LAZY_INSTANCE_INITIALIZER;
+
+HostSharedBitmapManager::HostSharedBitmapManager() {}
+HostSharedBitmapManager::~HostSharedBitmapManager() {}
+
+HostSharedBitmapManager* HostSharedBitmapManager::current() {
+ return g_shared_memory_manager.Pointer();
+}
+
+scoped_ptr<cc::SharedBitmap> HostSharedBitmapManager::AllocateSharedBitmap(
+ const gfx::Size& size) {
+ // Bitmaps allocated in host don't need to be shared to other processes, so
+ // allocate them with new instead.
+ return scoped_ptr<cc::SharedBitmap>();
+}
+
+scoped_ptr<cc::SharedBitmap> HostSharedBitmapManager::GetSharedBitmapFromId(
+ const gfx::Size& size,
+ const cc::SharedBitmapId& id) {
+ base::AutoLock lock(lock_);
+ BitmapMap::iterator it = handle_map_.find(id);
+ if (it == handle_map_.end())
+ return scoped_ptr<cc::SharedBitmap>();
+
+ BitmapData* data = it->second.get();
+
+ size_t bitmap_size;
+ if (!cc::SharedBitmap::GetSizeInBytes(size, &bitmap_size) ||
+ bitmap_size > data->buffer_size)
+ return scoped_ptr<cc::SharedBitmap>();
+
+ if (!data->memory->memory()) {
+ TRACE_EVENT0("renderer_host",
+ "HostSharedBitmapManager::GetSharedBitmapFromId");
+ if (!data->memory->Map(data->buffer_size)) {
+ return scoped_ptr<cc::SharedBitmap>();
+ }
+ }
+
+ scoped_ptr<cc::SharedBitmap> bitmap(new cc::SharedBitmap(
+ data->memory.get(), id, base::Bind(&FreeSharedMemory, it->second)));
+
+ return bitmap.Pass();
+}
+
+scoped_ptr<cc::SharedBitmap> HostSharedBitmapManager::GetBitmapForSharedMemory(
+ base::SharedMemory*) {
+ return scoped_ptr<cc::SharedBitmap>();
+}
+
+void HostSharedBitmapManager::ChildAllocatedSharedBitmap(
+ size_t buffer_size,
+ const base::SharedMemoryHandle& handle,
+ base::ProcessHandle process_handle,
+ const cc::SharedBitmapId& id) {
+ base::AutoLock lock(lock_);
+ if (handle_map_.find(id) != handle_map_.end())
+ return;
+ scoped_refptr<BitmapData> data(
+ new BitmapData(process_handle, handle, buffer_size));
+
+ handle_map_[id] = data;
+ process_map_[process_handle].insert(id);
+#if defined(OS_WIN)
+ data->memory = make_scoped_ptr(
+ new base::SharedMemory(data->memory_handle, false, data->process_handle));
+#else
+ data->memory =
+ make_scoped_ptr(new base::SharedMemory(data->memory_handle, false));
+#endif
+}
+
+void HostSharedBitmapManager::AllocateSharedBitmapForChild(
+ base::ProcessHandle process_handle,
+ size_t buffer_size,
+ const cc::SharedBitmapId& id,
+ base::SharedMemoryHandle* shared_memory_handle) {
+ base::AutoLock lock(lock_);
+ if (handle_map_.find(id) != handle_map_.end()) {
+ *shared_memory_handle = base::SharedMemory::NULLHandle();
+ return;
+ }
+ scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory);
+ if (!shared_memory->CreateAndMapAnonymous(buffer_size)) {
+ LOG(ERROR) << "Cannot create shared memory buffer";
+ *shared_memory_handle = base::SharedMemory::NULLHandle();
+ return;
+ }
+
+ scoped_refptr<BitmapData> data(
+ new BitmapData(process_handle, shared_memory->handle(), buffer_size));
+ data->memory = shared_memory.Pass();
+
+ handle_map_[id] = data;
+ process_map_[process_handle].insert(id);
+ if (!data->memory->ShareToProcess(process_handle, shared_memory_handle)) {
+ LOG(ERROR) << "Cannot share shared memory buffer";
+ *shared_memory_handle = base::SharedMemory::NULLHandle();
+ return;
+ }
+}
+
+void HostSharedBitmapManager::ChildDeletedSharedBitmap(
+ const cc::SharedBitmapId& id) {
+ base::AutoLock lock(lock_);
+ BitmapMap::iterator it = handle_map_.find(id);
+ if (it == handle_map_.end())
+ return;
+ base::hash_set<cc::SharedBitmapId>& res =
+ process_map_[it->second->process_handle];
+ res.erase(id);
+ handle_map_.erase(it);
+}
+
+void HostSharedBitmapManager::ProcessRemoved(
+ base::ProcessHandle process_handle) {
+ base::AutoLock lock(lock_);
+ ProcessMap::iterator proc_it = process_map_.find(process_handle);
+ if (proc_it == process_map_.end())
+ return;
+ base::hash_set<cc::SharedBitmapId>& res = proc_it->second;
+
+ for (base::hash_set<cc::SharedBitmapId>::iterator it = res.begin();
+ it != res.end();
+ ++it) {
+ handle_map_.erase(*it);
+ }
+ process_map_.erase(proc_it);
+}
+
+} // namespace content
diff --git a/content/common/host_shared_bitmap_manager.h b/content/common/host_shared_bitmap_manager.h
new file mode 100644
index 0000000..439abe6
--- /dev/null
+++ b/content/common/host_shared_bitmap_manager.h
@@ -0,0 +1,82 @@
+// Copyright (c) 2013 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 CONTENT_COMMON_HOST_SHARED_BITMAP_MANAGER_H_
+#define CONTENT_COMMON_HOST_SHARED_BITMAP_MANAGER_H_
+
+#include <map>
+#include <set>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/containers/hash_tables.h"
+#include "base/hash.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/shared_memory.h"
+#include "base/synchronization/lock.h"
+#include "cc/resources/shared_bitmap_manager.h"
+#include "content/common/content_export.h"
+
+namespace BASE_HASH_NAMESPACE {
+#if defined(COMPILER_GCC)
+template <>
+struct hash<cc::SharedBitmapId> {
+ size_t operator()(const cc::SharedBitmapId& id) const {
+ return base::Hash(reinterpret_cast<const char*>(id.name), sizeof(id.name));
+ }
+};
+#elif defined(COMPILER_MSVC)
+inline std::size_t hash_value(const cc::SharedBitmapId& id) {
+ return base::Hash(reinterpret_cast<const char*>(id.name), sizeof(id.name));
+}
+#endif // COMPILER
+} // namespace BASE_HASH_NAMESPACE
+
+namespace content {
+class BitmapData;
+
+class CONTENT_EXPORT HostSharedBitmapManager : public cc::SharedBitmapManager {
+ public:
+ HostSharedBitmapManager();
+ virtual ~HostSharedBitmapManager();
+
+ static HostSharedBitmapManager* current();
+
+ // cc::SharedBitmapManager implementation.
+ virtual scoped_ptr<cc::SharedBitmap> AllocateSharedBitmap(
+ const gfx::Size& size) OVERRIDE;
+ virtual scoped_ptr<cc::SharedBitmap> GetSharedBitmapFromId(
+ const gfx::Size& size,
+ const cc::SharedBitmapId&) OVERRIDE;
+ virtual scoped_ptr<cc::SharedBitmap> GetBitmapForSharedMemory(
+ base::SharedMemory*) OVERRIDE;
+
+ void AllocateSharedBitmapForChild(
+ base::ProcessHandle process_handle,
+ size_t buffer_size,
+ const cc::SharedBitmapId& id,
+ base::SharedMemoryHandle* shared_memory_handle);
+ void ChildAllocatedSharedBitmap(size_t buffer_size,
+ const base::SharedMemoryHandle& handle,
+ base::ProcessHandle process_handle,
+ const cc::SharedBitmapId& id);
+ void ChildDeletedSharedBitmap(const cc::SharedBitmapId& id);
+ void ProcessRemoved(base::ProcessHandle process_handle);
+
+ private:
+ base::Lock lock_;
+
+ typedef base::hash_map<cc::SharedBitmapId, scoped_refptr<BitmapData> >
+ BitmapMap;
+ BitmapMap handle_map_;
+
+ typedef base::hash_map<base::ProcessHandle,
+ base::hash_set<cc::SharedBitmapId> > ProcessMap;
+ ProcessMap process_map_;
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_HOST_SHARED_BITMAP_MANAGER_H_
diff --git a/content/common/host_shared_bitmap_manager_unittest.cc b/content/common/host_shared_bitmap_manager_unittest.cc
new file mode 100644
index 0000000..1f7d8dd
--- /dev/null
+++ b/content/common/host_shared_bitmap_manager_unittest.cc
@@ -0,0 +1,160 @@
+// Copyright (c) 2013 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 "content/common/host_shared_bitmap_manager.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+namespace {
+
+class HostSharedBitmapManagerTest : public testing::Test {
+ protected:
+ virtual void SetUp() { manager_.reset(new HostSharedBitmapManager()); }
+ scoped_ptr<HostSharedBitmapManager> manager_;
+};
+
+TEST_F(HostSharedBitmapManagerTest, TestCreate) {
+ gfx::Size bitmap_size(1, 1);
+ size_t size_in_bytes;
+ EXPECT_TRUE(cc::SharedBitmap::GetSizeInBytes(bitmap_size, &size_in_bytes));
+ scoped_ptr<base::SharedMemory> bitmap(new base::SharedMemory());
+ bitmap->CreateAndMapAnonymous(size_in_bytes);
+ memset(bitmap->memory(), 0xff, size_in_bytes);
+ cc::SharedBitmapId id = cc::SharedBitmap::GenerateId();
+
+ base::SharedMemoryHandle handle;
+ bitmap->ShareToProcess(base::GetCurrentProcessHandle(), &handle);
+ manager_->ChildAllocatedSharedBitmap(
+ size_in_bytes, handle, base::GetCurrentProcessHandle(), id);
+
+ scoped_ptr<cc::SharedBitmap> large_bitmap;
+ large_bitmap = manager_->GetSharedBitmapFromId(gfx::Size(1024, 1024), id);
+ EXPECT_TRUE(large_bitmap.get() == NULL);
+
+ scoped_ptr<cc::SharedBitmap> very_large_bitmap;
+ very_large_bitmap =
+ manager_->GetSharedBitmapFromId(gfx::Size(1, (1 << 30) | 1), id);
+ EXPECT_TRUE(very_large_bitmap.get() == NULL);
+
+ scoped_ptr<cc::SharedBitmap> negative_size_bitmap;
+ negative_size_bitmap =
+ manager_->GetSharedBitmapFromId(gfx::Size(-1, 1024), id);
+ EXPECT_TRUE(negative_size_bitmap.get() == NULL);
+
+ cc::SharedBitmapId id2 = cc::SharedBitmap::GenerateId();
+ scoped_ptr<cc::SharedBitmap> invalid_bitmap;
+ invalid_bitmap = manager_->GetSharedBitmapFromId(bitmap_size, id2);
+ EXPECT_TRUE(invalid_bitmap.get() == NULL);
+
+ scoped_ptr<cc::SharedBitmap> shared_bitmap;
+ shared_bitmap = manager_->GetSharedBitmapFromId(bitmap_size, id);
+ ASSERT_TRUE(shared_bitmap.get() != NULL);
+ EXPECT_EQ(memcmp(shared_bitmap->pixels(), bitmap->memory(), 4), 0);
+
+ scoped_ptr<cc::SharedBitmap> large_bitmap2;
+ large_bitmap2 = manager_->GetSharedBitmapFromId(gfx::Size(1024, 1024), id);
+ EXPECT_TRUE(large_bitmap2.get() == NULL);
+
+ scoped_ptr<cc::SharedBitmap> shared_bitmap2;
+ shared_bitmap2 = manager_->GetSharedBitmapFromId(bitmap_size, id);
+ EXPECT_TRUE(shared_bitmap2->pixels() == shared_bitmap->pixels());
+ shared_bitmap2.reset();
+ EXPECT_EQ(memcmp(shared_bitmap->pixels(), bitmap->memory(), size_in_bytes),
+ 0);
+
+ manager_->ChildDeletedSharedBitmap(id);
+
+ memset(bitmap->memory(), 0, size_in_bytes);
+
+ EXPECT_EQ(memcmp(shared_bitmap->pixels(), bitmap->memory(), size_in_bytes),
+ 0);
+ bitmap.reset();
+ shared_bitmap.reset();
+}
+
+TEST_F(HostSharedBitmapManagerTest, TestCreateForChild) {
+ gfx::Size bitmap_size(1, 1);
+ size_t size_in_bytes;
+ EXPECT_TRUE(cc::SharedBitmap::GetSizeInBytes(bitmap_size, &size_in_bytes));
+ cc::SharedBitmapId id = cc::SharedBitmap::GenerateId();
+ base::SharedMemoryHandle handle;
+ manager_->AllocateSharedBitmapForChild(
+ base::GetCurrentProcessHandle(), size_in_bytes, id, &handle);
+
+ EXPECT_TRUE(base::SharedMemory::IsHandleValid(handle));
+ scoped_ptr<base::SharedMemory> bitmap(new base::SharedMemory(handle, false));
+ EXPECT_TRUE(bitmap->Map(size_in_bytes));
+ memset(bitmap->memory(), 0xff, size_in_bytes);
+
+ scoped_ptr<cc::SharedBitmap> shared_bitmap;
+ shared_bitmap = manager_->GetSharedBitmapFromId(bitmap_size, id);
+ EXPECT_TRUE(shared_bitmap);
+ EXPECT_TRUE(
+ memcmp(bitmap->memory(), shared_bitmap->pixels(), size_in_bytes) == 0);
+}
+
+TEST_F(HostSharedBitmapManagerTest, RemoveProcess) {
+ gfx::Size bitmap_size(1, 1);
+ size_t size_in_bytes;
+ EXPECT_TRUE(cc::SharedBitmap::GetSizeInBytes(bitmap_size, &size_in_bytes));
+ scoped_ptr<base::SharedMemory> bitmap(new base::SharedMemory());
+ bitmap->CreateAndMapAnonymous(size_in_bytes);
+ memset(bitmap->memory(), 0xff, size_in_bytes);
+ cc::SharedBitmapId id = cc::SharedBitmap::GenerateId();
+
+ base::SharedMemoryHandle handle;
+ bitmap->ShareToProcess(base::GetCurrentProcessHandle(), &handle);
+ manager_->ChildAllocatedSharedBitmap(
+ size_in_bytes, handle, base::GetCurrentProcessHandle(), id);
+
+ manager_->ProcessRemoved(base::kNullProcessHandle);
+
+ scoped_ptr<cc::SharedBitmap> shared_bitmap;
+ shared_bitmap = manager_->GetSharedBitmapFromId(bitmap_size, id);
+ ASSERT_TRUE(shared_bitmap.get() != NULL);
+
+ manager_->ProcessRemoved(base::GetCurrentProcessHandle());
+
+ scoped_ptr<cc::SharedBitmap> shared_bitmap2;
+ shared_bitmap2 = manager_->GetSharedBitmapFromId(bitmap_size, id);
+ EXPECT_TRUE(shared_bitmap2.get() == NULL);
+ EXPECT_EQ(memcmp(shared_bitmap->pixels(), bitmap->memory(), size_in_bytes),
+ 0);
+
+ shared_bitmap.reset();
+
+ // Should no-op.
+ manager_->ChildDeletedSharedBitmap(id);
+}
+
+TEST_F(HostSharedBitmapManagerTest, AddDuplicate) {
+ gfx::Size bitmap_size(1, 1);
+ size_t size_in_bytes;
+ EXPECT_TRUE(cc::SharedBitmap::GetSizeInBytes(bitmap_size, &size_in_bytes));
+ scoped_ptr<base::SharedMemory> bitmap(new base::SharedMemory());
+ bitmap->CreateAndMapAnonymous(size_in_bytes);
+ memset(bitmap->memory(), 0xff, size_in_bytes);
+ cc::SharedBitmapId id = cc::SharedBitmap::GenerateId();
+
+ base::SharedMemoryHandle handle;
+ bitmap->ShareToProcess(base::GetCurrentProcessHandle(), &handle);
+ manager_->ChildAllocatedSharedBitmap(
+ size_in_bytes, handle, base::GetCurrentProcessHandle(), id);
+
+ scoped_ptr<base::SharedMemory> bitmap2(new base::SharedMemory());
+ bitmap2->CreateAndMapAnonymous(size_in_bytes);
+ memset(bitmap2->memory(), 0x00, size_in_bytes);
+
+ manager_->ChildAllocatedSharedBitmap(
+ size_in_bytes, bitmap2->handle(), base::GetCurrentProcessHandle(), id);
+
+ scoped_ptr<cc::SharedBitmap> shared_bitmap;
+ shared_bitmap = manager_->GetSharedBitmapFromId(bitmap_size, id);
+ ASSERT_TRUE(shared_bitmap.get() != NULL);
+ EXPECT_EQ(memcmp(shared_bitmap->pixels(), bitmap->memory(), size_in_bytes),
+ 0);
+}
+
+} // namespace
+} // namespace content
diff --git a/content/content_child.gypi b/content/content_child.gypi
index 8e4abc1..cdd7e79 100644
--- a/content/content_child.gypi
+++ b/content/content_child.gypi
@@ -41,6 +41,8 @@
'child/child_process.h',
'child/child_resource_message_filter.cc',
'child/child_resource_message_filter.h',
+ 'child/child_shared_bitmap_manager.cc',
+ 'child/child_shared_bitmap_manager.h',
'child/child_thread.cc',
'child/child_thread.h',
'child/content_child_helpers.cc',
diff --git a/content/content_common.gypi b/content/content_common.gypi
index ca814f0..8e46bb5 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -257,6 +257,8 @@
'common/gpu/texture_image_transport_surface.h',
'common/handle_enumerator_win.cc',
'common/handle_enumerator_win.h',
+ 'common/host_shared_bitmap_manager.cc',
+ 'common/host_shared_bitmap_manager.h',
'common/image_messages.h',
'common/indexed_db/indexed_db_constants.h',
'common/indexed_db/indexed_db_key.cc',
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index 95ca3bb..d1154bf 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -523,6 +523,7 @@
'common/common_param_traits_unittest.cc',
'common/dom_storage/dom_storage_map_unittest.cc',
'common/gpu/gpu_memory_manager_unittest.cc',
+ 'common/host_shared_bitmap_manager_unittest.cc',
'common/indexed_db/indexed_db_key_unittest.cc',
'common/input/input_param_traits_unittest.cc',
'common/input/web_input_event_traits_unittest.cc',
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc
index 8f88197..5f1910d 100644
--- a/content/renderer/gpu/render_widget_compositor.cc
+++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -24,6 +24,7 @@
#include "cc/debug/micro_benchmark.h"
#include "cc/layers/layer.h"
#include "cc/trees/layer_tree_host.h"
+#include "content/child/child_shared_bitmap_manager.h"
#include "content/common/content_switches_internal.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/public/common/content_switches.h"
@@ -395,10 +396,13 @@ void RenderWidgetCompositor::Initialize(cc::LayerTreeSettings settings) {
RenderThreadImpl::current()->compositor_message_loop_proxy();
if (compositor_message_loop_proxy.get()) {
layer_tree_host_ = cc::LayerTreeHost::CreateThreaded(
- this, NULL, settings, compositor_message_loop_proxy);
+ this,
+ ChildThread::current()->shared_bitmap_manager(),
+ settings,
+ compositor_message_loop_proxy);
} else {
layer_tree_host_ = cc::LayerTreeHost::CreateSingleThreaded(
- this, this, NULL, settings);
+ this, this, ChildThread::current()->shared_bitmap_manager(), settings);
}
DCHECK(layer_tree_host_);
}
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc
index e31bcfd..76b4413 100644
--- a/ui/compositor/compositor.cc
+++ b/ui/compositor/compositor.cc
@@ -45,6 +45,7 @@ enum SwapType {
bool g_compositor_initialized = false;
base::Thread* g_compositor_thread = NULL;
+cc::SharedBitmapManager* g_shared_bitmap_manager;
ui::ContextFactory* g_context_factory = NULL;
@@ -249,9 +250,13 @@ Compositor::Compositor(gfx::AcceleratedWidget widget)
base::TimeTicks before_create = base::TimeTicks::Now();
if (!!g_compositor_thread) {
host_ = cc::LayerTreeHost::CreateThreaded(
- this, NULL, settings, g_compositor_thread->message_loop_proxy());
+ this,
+ g_shared_bitmap_manager,
+ settings,
+ g_compositor_thread->message_loop_proxy());
} else {
- host_ = cc::LayerTreeHost::CreateSingleThreaded(this, this, NULL, settings);
+ host_ = cc::LayerTreeHost::CreateSingleThreaded(
+ this, this, g_shared_bitmap_manager, settings);
}
UMA_HISTOGRAM_TIMES("GPU.CreateBrowserCompositor",
base::TimeTicks::Now() - before_create);
@@ -320,6 +325,11 @@ void Compositor::Terminate() {
g_compositor_initialized = false;
}
+// static
+void Compositor::SetSharedBitmapManager(cc::SharedBitmapManager* manager) {
+ g_shared_bitmap_manager = manager;
+}
+
void Compositor::ScheduleDraw() {
if (g_compositor_thread) {
host_->Composite(gfx::FrameTime::Now());
diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h
index 21c582e..f91a294 100644
--- a/ui/compositor/compositor.h
+++ b/ui/compositor/compositor.h
@@ -33,6 +33,7 @@ class ContextProvider;
class Layer;
class LayerTreeDebugState;
class LayerTreeHost;
+class SharedBitmapManager;
}
namespace gfx {
@@ -177,6 +178,7 @@ class COMPOSITOR_EXPORT Compositor
static bool WasInitializedWithThread();
static scoped_refptr<base::MessageLoopProxy> GetCompositorMessageLoop();
static void Terminate();
+ static void SetSharedBitmapManager(cc::SharedBitmapManager* manager);
// Schedules a redraw of the layer tree associated with this compositor.
void ScheduleDraw();