summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--content/browser/gpu/browser_gpu_channel_host_factory.cc24
-rw-r--r--content/browser/gpu/browser_gpu_channel_host_factory.h4
-rw-r--r--content/browser/renderer_host/render_message_filter.cc21
-rw-r--r--content/browser/renderer_host/render_message_filter.h4
-rw-r--r--content/common/child_process_host_impl.cc9
-rw-r--r--content/common/child_process_host_impl.h6
-rw-r--r--content/common/child_process_messages.h13
-rw-r--r--content/common/gpu/client/command_buffer_proxy_impl.cc54
-rw-r--r--content/common/gpu/client/command_buffer_proxy_impl.h9
-rw-r--r--content/common/gpu/client/gpu_channel_host.cc31
-rw-r--r--content/common/gpu/client/gpu_channel_host.h22
-rw-r--r--content/common/gpu/client/gpu_memory_buffer_impl.cc80
-rw-r--r--content/common/gpu/client/gpu_memory_buffer_impl.h45
-rw-r--r--content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc19
-rw-r--r--content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h9
-rw-r--r--content/common/gpu/gpu_command_buffer_stub.cc34
-rw-r--r--content/common/gpu/gpu_command_buffer_stub.h10
-rw-r--r--content/common/gpu/gpu_messages.h16
-rw-r--r--content/content_common.gypi2
-rw-r--r--content/renderer/render_thread_impl.cc42
-rw-r--r--content/renderer/render_thread_impl.h4
21 files changed, 451 insertions, 7 deletions
diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.cc b/content/browser/gpu/browser_gpu_channel_host_factory.cc
index 7bc6fca..2f04189 100644
--- a/content/browser/gpu/browser_gpu_channel_host_factory.cc
+++ b/content/browser/gpu/browser_gpu_channel_host_factory.cc
@@ -9,8 +9,9 @@
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/gpu/gpu_surface_tracker.h"
-#include "content/common/gpu/gpu_messages.h"
#include "content/common/child_process_host_impl.h"
+#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
+#include "content/common/gpu/gpu_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_client.h"
#include "ipc/ipc_forwarding_message_filter.h"
@@ -284,6 +285,27 @@ GpuChannelHost* BrowserGpuChannelHostFactory::EstablishGpuChannelSync(
return gpu_channel_.get();
}
+scoped_ptr<gfx::GpuMemoryBuffer>
+ BrowserGpuChannelHostFactory::AllocateGpuMemoryBuffer(
+ size_t width,
+ size_t height,
+ unsigned internalformat) {
+ if (!GpuMemoryBufferImpl::IsFormatValid(internalformat))
+ return scoped_ptr<gfx::GpuMemoryBuffer>();
+
+ size_t size = width * height *
+ GpuMemoryBufferImpl::BytesPerPixel(internalformat);
+ scoped_ptr<base::SharedMemory> shm(new base::SharedMemory());
+ if (!shm->CreateAnonymous(size))
+ return scoped_ptr<gfx::GpuMemoryBuffer>();
+
+ return make_scoped_ptr<gfx::GpuMemoryBuffer>(
+ new GpuMemoryBufferImpl(shm.Pass(),
+ width,
+ height,
+ internalformat));
+}
+
// static
void BrowserGpuChannelHostFactory::AddFilterOnIO(
int host_id,
diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.h b/content/browser/gpu/browser_gpu_channel_host_factory.h
index ca31183..0e10ece 100644
--- a/content/browser/gpu/browser_gpu_channel_host_factory.h
+++ b/content/browser/gpu/browser_gpu_channel_host_factory.h
@@ -38,6 +38,10 @@ class CONTENT_EXPORT BrowserGpuChannelHostFactory
virtual void DeleteImage(int32 image_idu, int32 sync_point) OVERRIDE;
virtual GpuChannelHost* EstablishGpuChannelSync(
CauseForGpuLaunch cause_for_gpu_launch) OVERRIDE;
+ virtual scoped_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBuffer(
+ size_t width,
+ size_t height,
+ unsigned internalformat) OVERRIDE;
// Specify a task runner and callback to be used for a set of messages. The
// callback will be set up on the current GpuProcessHost, identified by
diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc
index d7e32d0..7fd1870 100644
--- a/content/browser/renderer_host/render_message_filter.cc
+++ b/content/browser/renderer_host/render_message_filter.cc
@@ -398,6 +398,8 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message,
OnCheckNotificationPermission)
IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateSharedMemory,
OnAllocateSharedMemory)
+ IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer,
+ OnAllocateGpuMemoryBuffer)
#if defined(OS_POSIX) && !defined(TOOLKIT_GTK) && !defined(OS_ANDROID)
IPC_MESSAGE_HANDLER(ViewHostMsg_AllocTransportDIB, OnAllocTransportDIB)
IPC_MESSAGE_HANDLER(ViewHostMsg_FreeTransportDIB, OnFreeTransportDIB)
@@ -1165,4 +1167,23 @@ void RenderMessageFilter::OnWebAudioMediaCodec(
true);
}
#endif
+
+void RenderMessageFilter::OnAllocateGpuMemoryBuffer(
+ uint32 buffer_size,
+ gfx::GpuMemoryBufferHandle* handle) {
+ // TODO(reveman): Implement allocation of real GpuMemoryBuffer.
+ // Currently this function creates a fake GpuMemoryBuffer that is
+ // backed by shared memory and requires an upload before it can
+ // be used as a texture. The plan is to instead have this function
+ // allocate a real GpuMemoryBuffer in whatever form is supported
+ // by platform and drivers.
+ //
+ // Note: |buffer_size| likely needs to be replaced by a more
+ // specific buffer description but is enough for the shared memory
+ // backed GpuMemoryBuffer currently returned.
+ handle->type = gfx::SHARED_MEMORY_BUFFER;
+ ChildProcessHostImpl::AllocateSharedMemory(
+ buffer_size, PeerHandle(), &handle->handle);
+}
+
} // namespace content
diff --git a/content/browser/renderer_host/render_message_filter.h b/content/browser/renderer_host/render_message_filter.h
index 446a531..d0a4386 100644
--- a/content/browser/renderer_host/render_message_filter.h
+++ b/content/browser/renderer_host/render_message_filter.h
@@ -52,6 +52,7 @@ class TaskRunner;
namespace gfx {
class Rect;
+struct GpuMemoryBufferHandle;
}
namespace media {
@@ -261,6 +262,9 @@ class RenderMessageFilter : public BrowserMessageFilter {
uint32_t data_size);
#endif
+ void OnAllocateGpuMemoryBuffer(uint32 buffer_size,
+ gfx::GpuMemoryBufferHandle* handle);
+
// Cached resource request dispatcher host and plugin service, guaranteed to
// be non-null if Init succeeds. We do not own the objects, they are managed
// by the BrowserProcess, which has a wider scope than we do.
diff --git a/content/common/child_process_host_impl.cc b/content/common/child_process_host_impl.cc
index fb058d3..a2f40d4 100644
--- a/content/common/child_process_host_impl.cc
+++ b/content/common/child_process_host_impl.cc
@@ -247,6 +247,8 @@ bool ChildProcessHostImpl::OnMessageReceived(const IPC::Message& msg) {
OnShutdownRequest)
IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateSharedMemory,
OnAllocateSharedMemory)
+ IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer,
+ OnAllocateGpuMemoryBuffer)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -293,4 +295,11 @@ void ChildProcessHostImpl::OnShutdownRequest() {
Send(new ChildProcessMsg_Shutdown());
}
+void ChildProcessHostImpl::OnAllocateGpuMemoryBuffer(
+ uint32 buffer_size,
+ gfx::GpuMemoryBufferHandle* handle) {
+ handle->type = gfx::SHARED_MEMORY_BUFFER;
+ AllocateSharedMemory(buffer_size, peer_handle_, &handle->handle);
+}
+
} // namespace content
diff --git a/content/common/child_process_host_impl.h b/content/common/child_process_host_impl.h
index a24f3b8..74700bc 100644
--- a/content/common/child_process_host_impl.h
+++ b/content/common/child_process_host_impl.h
@@ -22,6 +22,10 @@ namespace base {
class FilePath;
}
+namespace gfx {
+struct GpuMemoryBufferHandle;
+}
+
namespace content {
class ChildProcessHostDelegate;
@@ -75,6 +79,8 @@ class CONTENT_EXPORT ChildProcessHostImpl : public ChildProcessHost,
void OnShutdownRequest();
void OnAllocateSharedMemory(uint32 buffer_size,
base::SharedMemoryHandle* handle);
+ void OnAllocateGpuMemoryBuffer(uint32 buffer_size,
+ gfx::GpuMemoryBufferHandle* handle);
ChildProcessHostDelegate* delegate_;
base::ProcessHandle peer_handle_;
diff --git a/content/common/child_process_messages.h b/content/common/child_process_messages.h
index 3f70bc3..c122588 100644
--- a/content/common/child_process_messages.h
+++ b/content/common/child_process_messages.h
@@ -13,6 +13,7 @@
#include "base/values.h"
#include "content/common/content_export.h"
#include "ipc/ipc_message_macros.h"
+#include "ui/gfx/gpu_memory_buffer.h"
IPC_ENUM_TRAITS(tracked_objects::ThreadData::Status)
@@ -54,6 +55,13 @@ IPC_STRUCT_TRAITS_BEGIN(tracked_objects::ProcessDataSnapshot)
IPC_STRUCT_TRAITS_MEMBER(process_id)
IPC_STRUCT_TRAITS_END()
+IPC_ENUM_TRAITS(gfx::GpuMemoryBufferType)
+
+IPC_STRUCT_TRAITS_BEGIN(gfx::GpuMemoryBufferHandle)
+ IPC_STRUCT_TRAITS_MEMBER(type)
+ IPC_STRUCT_TRAITS_MEMBER(handle)
+IPC_STRUCT_TRAITS_END()
+
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
@@ -138,3 +146,8 @@ IPC_SYNC_MESSAGE_CONTROL1_1(ChildProcessHostMsg_SyncAllocateSharedMemory,
IPC_MESSAGE_CONTROL1(ChildProcessHostMsg_TcmallocStats,
std::string /* output */)
#endif
+
+// Asks the browser to create a gpu memory buffer.
+IPC_SYNC_MESSAGE_CONTROL1_1(ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer,
+ uint32 /* buffer size */,
+ gfx::GpuMemoryBufferHandle)
diff --git a/content/common/gpu/client/command_buffer_proxy_impl.cc b/content/common/gpu/client/command_buffer_proxy_impl.cc
index 94abbe1..3fbe537 100644
--- a/content/common/gpu/client/command_buffer_proxy_impl.cc
+++ b/content/common/gpu/client/command_buffer_proxy_impl.cc
@@ -367,7 +367,7 @@ void CommandBufferProxyImpl::SetContextLostReason(
}
bool CommandBufferProxyImpl::SupportsGpuMemoryBuffer() {
- return false;
+ return true;
}
gfx::GpuMemoryBuffer* CommandBufferProxyImpl::CreateGpuMemoryBuffer(
@@ -375,12 +375,58 @@ gfx::GpuMemoryBuffer* CommandBufferProxyImpl::CreateGpuMemoryBuffer(
size_t height,
unsigned internalformat,
int32* id) {
- NOTREACHED();
- return NULL;
+ *id = -1;
+
+ if (last_state_.error != gpu::error::kNoError)
+ return NULL;
+
+ int32 new_id = channel_->ReserveGpuMemoryBufferId();
+ DCHECK(gpu_memory_buffers_.find(new_id) == gpu_memory_buffers_.end());
+
+ scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer(
+ channel_->factory()->AllocateGpuMemoryBuffer(width,
+ height,
+ internalformat));
+ if (!gpu_memory_buffer)
+ return NULL;
+
+ DCHECK(GpuChannelHost::IsValidGpuMemoryBuffer(
+ gpu_memory_buffer->GetHandle()));
+
+ // This handle is owned by the GPU process and must be passed to it or it
+ // will leak. In otherwords, do not early out on error between here and the
+ // sending of the RegisterGpuMemoryBuffer IPC below.
+ gfx::GpuMemoryBufferHandle handle =
+ channel_->ShareGpuMemoryBufferToGpuProcess(
+ gpu_memory_buffer->GetHandle());
+
+ if (!Send(new GpuCommandBufferMsg_RegisterGpuMemoryBuffer(
+ route_id_,
+ new_id,
+ handle,
+ width,
+ height,
+ internalformat))) {
+ return NULL;
+ }
+
+ *id = new_id;
+ gpu_memory_buffers_[new_id] = gpu_memory_buffer.release();
+ return gpu_memory_buffers_[new_id];
}
void CommandBufferProxyImpl::DestroyGpuMemoryBuffer(int32 id) {
- NOTREACHED();
+ if (last_state_.error != gpu::error::kNoError)
+ return;
+
+ // Remove the gpu memory buffer from the client side cache.
+ GpuMemoryBufferMap::iterator it = gpu_memory_buffers_.find(id);
+ if (it != gpu_memory_buffers_.end()) {
+ delete it->second;
+ gpu_memory_buffers_.erase(it);
+ }
+
+ Send(new GpuCommandBufferMsg_DestroyGpuMemoryBuffer(route_id_, id));
}
int CommandBufferProxyImpl::GetRouteID() const {
diff --git a/content/common/gpu/client/command_buffer_proxy_impl.h b/content/common/gpu/client/command_buffer_proxy_impl.h
index c891483..35255a9 100644
--- a/content/common/gpu/client/command_buffer_proxy_impl.h
+++ b/content/common/gpu/client/command_buffer_proxy_impl.h
@@ -16,7 +16,6 @@
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "content/common/gpu/gpu_memory_allocation.h"
-#include "content/common/gpu/gpu_memory_allocation.h"
#include "gpu/command_buffer/common/command_buffer.h"
#include "gpu/command_buffer/common/command_buffer_shared.h"
#include "gpu/command_buffer/common/gpu_control.h"
@@ -30,6 +29,10 @@ namespace base {
class SharedMemory;
}
+namespace gfx {
+class GpuMemoryBuffer;
+}
+
namespace gpu {
struct Mailbox;
}
@@ -145,6 +148,7 @@ class CommandBufferProxyImpl
private:
typedef std::map<int32, gpu::Buffer> TransferBufferMap;
typedef base::hash_map<uint32, base::Closure> SignalTaskMap;
+ typedef std::map<int32, gfx::GpuMemoryBuffer*> GpuMemoryBufferMap;
// Send an IPC message over the GPU channel. This is private to fully
// encapsulate the channel; all callers of this function must explicitly
@@ -202,6 +206,9 @@ class CommandBufferProxyImpl
uint32 next_signal_id_;
SignalTaskMap signal_tasks_;
+ // Local cache of id to gpu memory buffer mapping.
+ GpuMemoryBufferMap gpu_memory_buffers_;
+
DISALLOW_COPY_AND_ASSIGN(CommandBufferProxyImpl);
};
diff --git a/content/common/gpu/client/gpu_channel_host.cc b/content/common/gpu/client/gpu_channel_host.cc
index 27c71de..4624ec7 100644
--- a/content/common/gpu/client/gpu_channel_host.cc
+++ b/content/common/gpu/client/gpu_channel_host.cc
@@ -46,6 +46,17 @@ scoped_refptr<GpuChannelHost> GpuChannelHost::Create(
return host;
}
+// static
+bool GpuChannelHost::IsValidGpuMemoryBuffer(
+ gfx::GpuMemoryBufferHandle handle) {
+ switch (handle.type) {
+ case gfx::SHARED_MEMORY_BUFFER:
+ return true;
+ default:
+ return false;
+ }
+}
+
GpuChannelHost::GpuChannelHost(GpuChannelHostFactory* factory,
int gpu_host_id,
int client_id,
@@ -55,6 +66,7 @@ GpuChannelHost::GpuChannelHost(GpuChannelHostFactory* factory,
gpu_host_id_(gpu_host_id),
gpu_info_(gpu_info) {
next_transfer_buffer_id_.GetNext();
+ next_gpu_memory_buffer_id_.GetNext();
}
void GpuChannelHost::Connect(const IPC::ChannelHandle& channel_handle) {
@@ -285,6 +297,25 @@ int32 GpuChannelHost::ReserveTransferBufferId() {
return next_transfer_buffer_id_.GetNext();
}
+gfx::GpuMemoryBufferHandle GpuChannelHost::ShareGpuMemoryBufferToGpuProcess(
+ gfx::GpuMemoryBufferHandle source_handle) {
+ switch (source_handle.type) {
+ case gfx::SHARED_MEMORY_BUFFER: {
+ gfx::GpuMemoryBufferHandle handle;
+ handle.type = gfx::SHARED_MEMORY_BUFFER;
+ handle.handle = ShareToGpuProcess(source_handle.handle);
+ return handle;
+ }
+ default:
+ NOTREACHED();
+ return gfx::GpuMemoryBufferHandle();
+ }
+}
+
+int32 GpuChannelHost::ReserveGpuMemoryBufferId() {
+ return next_gpu_memory_buffer_id_.GetNext();
+}
+
GpuChannelHost::~GpuChannelHost() {
// channel_ must be destroyed on the main thread.
if (!factory_->IsMainThread())
diff --git a/content/common/gpu/client/gpu_channel_host.h b/content/common/gpu/client/gpu_channel_host.h
index 5efa98d..87240ef 100644
--- a/content/common/gpu/client/gpu_channel_host.h
+++ b/content/common/gpu/client/gpu_channel_host.h
@@ -24,6 +24,7 @@
#include "ipc/ipc_sync_channel.h"
#include "media/video/video_decode_accelerator.h"
#include "media/video/video_encode_accelerator.h"
+#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/size.h"
#include "ui/gl/gpu_preference.h"
@@ -77,6 +78,10 @@ class CONTENT_EXPORT GpuChannelHostFactory {
int32 image_id,
const CreateImageCallback& callback) = 0;
virtual void DeleteImage(int32 image_id, int32 sync_point) = 0;
+ virtual scoped_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBuffer(
+ size_t width,
+ size_t height,
+ unsigned internalformat) = 0;
};
// Encapsulates an IPC channel between the client and one GPU process.
@@ -94,6 +99,10 @@ class GpuChannelHost : public IPC::Sender,
const gpu::GPUInfo& gpu_info,
const IPC::ChannelHandle& channel_handle);
+ // Returns true if |handle| is a valid GpuMemoryBuffer handle that
+ // can be shared to the GPU process.
+ static bool IsValidGpuMemoryBuffer(gfx::GpuMemoryBufferHandle handle);
+
bool IsLost() const {
DCHECK(channel_filter_.get());
return channel_filter_->IsLost();
@@ -162,6 +171,15 @@ class GpuChannelHost : public IPC::Sender,
// Reserve one unused transfer buffer ID.
int32 ReserveTransferBufferId();
+ // Returns a GPU memory buffer handle to the buffer that can be sent via
+ // IPC to the GPU process. The caller is responsible for ensuring it is
+ // closed. Returns an invalid handle on failure.
+ gfx::GpuMemoryBufferHandle ShareGpuMemoryBufferToGpuProcess(
+ gfx::GpuMemoryBufferHandle source_handle);
+
+ // Reserve one unused gpu memory buffer ID.
+ int32 ReserveGpuMemoryBufferId();
+
private:
friend class base::RefCountedThreadSafe<GpuChannelHost>;
GpuChannelHost(GpuChannelHostFactory* factory,
@@ -228,6 +246,7 @@ class GpuChannelHost : public IPC::Sender,
// Threading notes: all fields are constant during the lifetime of |this|
// except:
// - |next_transfer_buffer_id_|, atomic type
+ // - |next_gpu_memory_buffer_id_|, atomic type
// - |proxies_|, protected by |context_lock_|
GpuChannelHostFactory* const factory_;
const int client_id_;
@@ -244,6 +263,9 @@ class GpuChannelHost : public IPC::Sender,
// Transfer buffer IDs are allocated in sequence.
base::AtomicSequenceNumber next_transfer_buffer_id_;
+ // Gpu memory buffer IDs are allocated in sequence.
+ base::AtomicSequenceNumber next_gpu_memory_buffer_id_;
+
// Protects proxies_.
mutable base::Lock context_lock_;
// Used to look up a proxy from its routing id.
diff --git a/content/common/gpu/client/gpu_memory_buffer_impl.cc b/content/common/gpu/client/gpu_memory_buffer_impl.cc
new file mode 100644
index 0000000..e5f6bc5
--- /dev/null
+++ b/content/common/gpu/client/gpu_memory_buffer_impl.cc
@@ -0,0 +1,80 @@
+// 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/gpu/client/gpu_memory_buffer_impl.h"
+
+#include "ui/gl/gl_bindings.h"
+
+namespace content {
+
+GpuMemoryBufferImpl::GpuMemoryBufferImpl(
+ scoped_ptr<base::SharedMemory> shared_memory,
+ size_t width,
+ size_t height,
+ unsigned internalformat)
+ : shared_memory_(shared_memory.Pass()),
+ size_(gfx::Size(width, height)),
+ internalformat_(internalformat),
+ mapped_(false) {
+ DCHECK(!shared_memory_->memory());
+ DCHECK(IsFormatValid(internalformat));
+}
+
+GpuMemoryBufferImpl::~GpuMemoryBufferImpl() {
+}
+
+void GpuMemoryBufferImpl::Map(AccessMode mode, void** vaddr) {
+ DCHECK(!mapped_);
+ *vaddr = NULL;
+ if (!shared_memory_->Map(size_.GetArea() * BytesPerPixel(internalformat_)))
+ return;
+ *vaddr = shared_memory_->memory();
+ mapped_ = true;
+}
+
+void GpuMemoryBufferImpl::Unmap() {
+ DCHECK(mapped_);
+ shared_memory_->Unmap();
+ mapped_ = false;
+}
+
+bool GpuMemoryBufferImpl::IsMapped() const {
+ return mapped_;
+}
+
+uint32 GpuMemoryBufferImpl::GetStride() const {
+ return size_.width() * BytesPerPixel(internalformat_);
+}
+
+gfx::GpuMemoryBufferHandle GpuMemoryBufferImpl::GetHandle() const {
+ gfx::GpuMemoryBufferHandle handle;
+ handle.type = gfx::SHARED_MEMORY_BUFFER;
+ handle.handle = shared_memory_->handle();
+ return handle;
+}
+
+// static
+bool GpuMemoryBufferImpl::IsFormatValid(unsigned internalformat) {
+ // GL_RGBA8_OES is the only supported format at the moment.
+ switch (internalformat) {
+ case GL_RGBA8_OES:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// static
+size_t GpuMemoryBufferImpl::BytesPerPixel(unsigned internalformat) {
+ // GL_RGBA_OES has 4 bytes per pixel.
+ switch (internalformat) {
+ case GL_RGBA8_OES:
+ return 4;
+ default:
+ NOTREACHED();
+ return 0;
+ }
+}
+
+} // namespace content
diff --git a/content/common/gpu/client/gpu_memory_buffer_impl.h b/content/common/gpu/client/gpu_memory_buffer_impl.h
new file mode 100644
index 0000000..3858c3f
--- /dev/null
+++ b/content/common/gpu/client/gpu_memory_buffer_impl.h
@@ -0,0 +1,45 @@
+// 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.
+
+#ifndef CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_H_
+#define CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "ui/gfx/gpu_memory_buffer.h"
+#include "ui/gfx/size.h"
+
+namespace content {
+
+// Provides common implementation of a GPU memory buffer based
+// on a shared memory handle.
+class GpuMemoryBufferImpl : public gfx::GpuMemoryBuffer {
+ public:
+ GpuMemoryBufferImpl(scoped_ptr<base::SharedMemory> shared_memory,
+ size_t width,
+ size_t height,
+ unsigned internalformat);
+ virtual ~GpuMemoryBufferImpl();
+
+ // Overridden from gfx::GpuMemoryBuffer:
+ virtual void Map(AccessMode mode, void** vaddr) OVERRIDE;
+ virtual void Unmap() OVERRIDE;
+ virtual bool IsMapped() const OVERRIDE;
+ virtual uint32 GetStride() const OVERRIDE;
+ virtual gfx::GpuMemoryBufferHandle GetHandle() const OVERRIDE;
+
+ static bool IsFormatValid(unsigned internalformat);
+ static size_t BytesPerPixel(unsigned internalformat);
+
+ private:
+ scoped_ptr<base::SharedMemory> shared_memory_;
+ const gfx::Size size_;
+ unsigned internalformat_;
+ bool mapped_;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_H_
diff --git a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc
index bd4ebab..ccbde6f 100644
--- a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc
+++ b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc
@@ -147,6 +147,11 @@ void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3) { \
gl_->glname(a1, a2, a3); \
}
+#define DELEGATE_TO_GL_3R(name, glname, t1, t2, t3, rt) \
+rt WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3) { \
+ return gl_->glname(a1, a2, a3); \
+}
+
#define DELEGATE_TO_GL_4(name, glname, t1, t2, t3, t4) \
void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, \
t4 a4) { \
@@ -1525,6 +1530,20 @@ void WebGraphicsContext3DCommandBufferImpl::drawElementsInstancedANGLE(
DELEGATE_TO_GL_2(vertexAttribDivisorANGLE, VertexAttribDivisorANGLE, WGC3Duint,
WGC3Duint)
+DELEGATE_TO_GL_3R(createImageCHROMIUM, CreateImageCHROMIUM,
+ WGC3Dsizei, WGC3Dsizei, WGC3Denum,
+ WGC3Duint);
+
+DELEGATE_TO_GL_1(destroyImageCHROMIUM, DestroyImageCHROMIUM, WGC3Duint);
+
+DELEGATE_TO_GL_3(getImageParameterivCHROMIUM, GetImageParameterivCHROMIUM,
+ WGC3Duint, WGC3Denum, GLint*);
+
+DELEGATE_TO_GL_2R(mapImageCHROMIUM, MapImageCHROMIUM,
+ WGC3Duint, WGC3Denum, void*);
+
+DELEGATE_TO_GL_1(unmapImageCHROMIUM, UnmapImageCHROMIUM, WGC3Duint);
+
GrGLInterface* WebGraphicsContext3DCommandBufferImpl::createGrGLInterface() {
return webkit::gpu::CreateCommandBufferSkiaGLBinding();
}
diff --git a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h
index 7a03d33..59eb665 100644
--- a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h
+++ b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h
@@ -640,6 +640,15 @@ class WebGraphicsContext3DCommandBufferImpl
WGC3Denum type, WGC3Dintptr offset, WGC3Dsizei primcount);
virtual void vertexAttribDivisorANGLE(WGC3Duint index, WGC3Duint divisor);
+ // GL_CHROMIUM_map_image
+ virtual WGC3Duint createImageCHROMIUM(
+ WGC3Dsizei width, WGC3Dsizei height, WGC3Denum internalformat);
+ virtual void destroyImageCHROMIUM(WGC3Duint image_id);
+ virtual void getImageParameterivCHROMIUM(
+ WGC3Duint image_id, WGC3Denum pname, WGC3Dint* params);
+ virtual void* mapImageCHROMIUM(WGC3Duint image_id, WGC3Denum access);
+ virtual void unmapImageCHROMIUM(WGC3Duint image_id);
+
virtual GrGLInterface* createGrGLInterface();
private:
diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc
index 05792bf..9030ffe 100644
--- a/content/common/gpu/gpu_command_buffer_stub.cc
+++ b/content/common/gpu/gpu_command_buffer_stub.cc
@@ -26,6 +26,8 @@
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/service/gl_context_virtual.h"
#include "gpu/command_buffer/service/gl_state_restorer_impl.h"
+#include "gpu/command_buffer/service/gpu_control_service.h"
+#include "gpu/command_buffer/service/image_manager.h"
#include "gpu/command_buffer/service/logger.h"
#include "gpu/command_buffer/service/memory_tracking.h"
#include "gpu/command_buffer/service/query_manager.h"
@@ -223,6 +225,10 @@ bool GpuCommandBufferStub::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(
GpuCommandBufferMsg_SetClientHasMemoryAllocationChangedCallback,
OnSetClientHasMemoryAllocationChangedCallback)
+ IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_RegisterGpuMemoryBuffer,
+ OnRegisterGpuMemoryBuffer);
+ IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_DestroyGpuMemoryBuffer,
+ OnDestroyGpuMemoryBuffer);
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -403,6 +409,12 @@ void GpuCommandBufferStub::OnInitialize(
return;
}
+ gpu_control_.reset(
+ new gpu::GpuControlService(context_group_->image_manager(),
+ NULL,
+ context_group_->mailbox_manager(),
+ NULL));
+
decoder_.reset(::gpu::gles2::GLES2Decoder::Create(context_group_.get()));
scheduler_.reset(new gpu::GpuScheduler(command_buffer_.get(),
@@ -848,6 +860,28 @@ void GpuCommandBufferStub::OnSetClientHasMemoryAllocationChangedCallback(
}
}
+void GpuCommandBufferStub::OnRegisterGpuMemoryBuffer(
+ int32 id,
+ gfx::GpuMemoryBufferHandle gpu_memory_buffer,
+ uint32 width,
+ uint32 height,
+ uint32 internalformat) {
+ TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnRegisterGpuMemoryBuffer");
+ if (gpu_control_) {
+ gpu_control_->RegisterGpuMemoryBuffer(id,
+ gpu_memory_buffer,
+ width,
+ height,
+ internalformat);
+ }
+}
+
+void GpuCommandBufferStub::OnDestroyGpuMemoryBuffer(int32 id) {
+ TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnDestroyGpuMemoryBuffer");
+ if (gpu_control_)
+ gpu_control_->DestroyGpuMemoryBuffer(id);
+}
+
void GpuCommandBufferStub::SendConsoleMessage(
int32 id,
const std::string& message) {
diff --git a/content/common/gpu/gpu_command_buffer_stub.h b/content/common/gpu/gpu_command_buffer_stub.h
index 47c532b..a5258f2 100644
--- a/content/common/gpu/gpu_command_buffer_stub.h
+++ b/content/common/gpu/gpu_command_buffer_stub.h
@@ -24,6 +24,7 @@
#include "ipc/ipc_sender.h"
#include "media/base/video_decoder_config.h"
#include "ui/events/latency_info.h"
+#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/size.h"
#include "ui/gl/gl_surface.h"
@@ -31,6 +32,7 @@
#include "url/gurl.h"
namespace gpu {
+class GpuControlService;
struct Mailbox;
namespace gles2 {
class ImageManager;
@@ -181,6 +183,13 @@ class GpuCommandBufferStub
void OnReceivedClientManagedMemoryStats(const GpuManagedMemoryStats& stats);
void OnSetClientHasMemoryAllocationChangedCallback(bool has_callback);
+ void OnRegisterGpuMemoryBuffer(int32 id,
+ gfx::GpuMemoryBufferHandle gpu_memory_buffer,
+ uint32 width,
+ uint32 height,
+ uint32 internalformat);
+ void OnDestroyGpuMemoryBuffer(int32 id);
+
void OnCommandProcessed();
void OnParseError();
void OnSetLatencyInfo(const ui::LatencyInfo& latency_info);
@@ -223,6 +232,7 @@ class GpuCommandBufferStub
scoped_ptr<gpu::gles2::GLES2Decoder> decoder_;
scoped_ptr<gpu::GpuScheduler> scheduler_;
scoped_refptr<gfx::GLSurface> surface_;
+ scoped_ptr<gpu::GpuControlService> gpu_control_;
scoped_ptr<GpuMemoryManagerClientState> memory_manager_client_state_;
// The last memory allocation received from the GpuMemoryManager (used to
diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h
index 124815b..3c2bb28 100644
--- a/content/common/gpu/gpu_messages.h
+++ b/content/common/gpu/gpu_messages.h
@@ -27,6 +27,7 @@
#include "media/video/video_decode_accelerator.h"
#include "media/video/video_encode_accelerator.h"
#include "ui/events/latency_info.h"
+#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/size.h"
#include "ui/gl/gpu_preference.h"
@@ -548,7 +549,7 @@ IPC_MESSAGE_ROUTED0(GpuCommandBufferMsg_Rescheduled)
IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_ConsoleMsg,
GPUCommandBufferConsoleMessage /* msg */)
-// Register an existing shared memory transfer buffer. Returns an id that can be
+// Register an existing shared memory transfer buffer. The id that can be
// used to identify the transfer buffer from a command buffer.
IPC_MESSAGE_ROUTED3(GpuCommandBufferMsg_RegisterTransferBuffer,
int32 /* id */,
@@ -637,6 +638,19 @@ IPC_MESSAGE_ROUTED2(GpuCommandBufferMsg_SignalQuery,
uint32 /* query */,
uint32 /* signal_id */)
+// Register an existing gpu memory buffer. The id that can be
+// used to identify the gpu memory buffer from a command buffer.
+IPC_MESSAGE_ROUTED5(GpuCommandBufferMsg_RegisterGpuMemoryBuffer,
+ int32 /* id */,
+ gfx::GpuMemoryBufferHandle /* gpu_memory_buffer */,
+ uint32 /* width */,
+ uint32 /* height */,
+ uint32 /* internalformat */)
+
+// Destroy a previously created gpu memory buffer.
+IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_DestroyGpuMemoryBuffer,
+ int32 /* id */)
+
//------------------------------------------------------------------------------
// Accelerated Video Decoder Messages
// These messages are sent from Renderer process to GPU process.
diff --git a/content/content_common.gypi b/content/content_common.gypi
index 18edca34..ef8293d 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -190,6 +190,8 @@
'common/gpu/client/gl_helper_scaling.h',
'common/gpu/client/gpu_channel_host.cc',
'common/gpu/client/gpu_channel_host.h',
+ 'common/gpu/client/gpu_memory_buffer_impl.cc',
+ 'common/gpu/client/gpu_memory_buffer_impl.h',
'common/gpu/client/gpu_video_decode_accelerator_host.cc',
'common/gpu/client/gpu_video_decode_accelerator_host.h',
'common/gpu/client/gpu_video_encode_accelerator_host.cc',
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 4f719e3..aa5b565 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -44,6 +44,7 @@
#include "content/common/dom_storage/dom_storage_messages.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/common/gpu/client/gpu_channel_host.h"
+#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/common/resource_messages.h"
#include "content/common/view_messages.h"
@@ -1052,6 +1053,47 @@ void RenderThreadImpl::DeleteImage(int32 image_id, int32 sync_point) {
NOTREACHED();
}
+scoped_ptr<gfx::GpuMemoryBuffer> RenderThreadImpl::AllocateGpuMemoryBuffer(
+ size_t width,
+ size_t height,
+ unsigned internalformat) {
+ if (!GpuMemoryBufferImpl::IsFormatValid(internalformat))
+ return scoped_ptr<gfx::GpuMemoryBuffer>();
+
+ size_t size = width * height *
+ GpuMemoryBufferImpl::BytesPerPixel(internalformat);
+ if (size > static_cast<size_t>(std::numeric_limits<int>::max()))
+ return scoped_ptr<gfx::GpuMemoryBuffer>();
+
+ gfx::GpuMemoryBufferHandle handle;
+ bool success;
+ IPC::Message* message =
+ new ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer(size, &handle);
+
+ // Allow calling this from the compositor thread.
+ if (base::MessageLoop::current() == message_loop())
+ success = ChildThread::Send(message);
+ else
+ success = sync_message_filter()->Send(message);
+
+ if (!success)
+ return scoped_ptr<gfx::GpuMemoryBuffer>();
+
+ // Currently, shared memory is the only supported buffer type.
+ if (handle.type != gfx::SHARED_MEMORY_BUFFER)
+ return scoped_ptr<gfx::GpuMemoryBuffer>();
+
+ if (!base::SharedMemory::IsHandleValid(handle.handle))
+ return scoped_ptr<gfx::GpuMemoryBuffer>();
+
+ return make_scoped_ptr<gfx::GpuMemoryBuffer>(
+ new GpuMemoryBufferImpl(
+ make_scoped_ptr(new base::SharedMemory(handle.handle, false)),
+ width,
+ height,
+ internalformat));
+}
+
void RenderThreadImpl::DoNotSuspendWebKitSharedTimer() {
suspend_webkit_shared_timer_ = false;
}
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index b2e7e9b..e1f4ec9 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -364,6 +364,10 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
int32 image_id,
const CreateImageCallback& callback) OVERRIDE;
virtual void DeleteImage(int32 image_id, int32 sync_point) OVERRIDE;
+ virtual scoped_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBuffer(
+ size_t width,
+ size_t height,
+ unsigned internalformat) OVERRIDE;
void Init();