diff options
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(); |