diff options
author | reveman@chromium.org <reveman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-05 01:02:12 +0000 |
---|---|---|
committer | reveman@chromium.org <reveman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-05 01:02:12 +0000 |
commit | 8810516771cd7414f6d05f851666061b6b8bca9a (patch) | |
tree | 545ddedbc70d6f32ccd035417e6def969528e037 | |
parent | 7b69f87961fa5e8a948df0072819424d0b041d3d (diff) | |
download | chromium_src-8810516771cd7414f6d05f851666061b6b8bca9a.zip chromium_src-8810516771cd7414f6d05f851666061b6b8bca9a.tar.gz chromium_src-8810516771cd7414f6d05f851666061b6b8bca9a.tar.bz2 |
gpu: Add IOSurface backed GpuMemoryBuffer implementation.
This adds a GpuMemoryBuffer implementation on MacOSX that is backed
by IOSurfaces. These GpuMemmoryBuffers provide zero-copy texture
updates when using impl-side painting on MacOSX.
BUG=321785,323338
Review URL: https://codereview.chromium.org/77023002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@238841 0039d316-1c4b-4281-b951-d872f2087c98
29 files changed, 784 insertions, 94 deletions
diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.cc b/content/browser/gpu/browser_gpu_channel_host_factory.cc index 5ac4a06..191f0f6 100644 --- a/content/browser/gpu/browser_gpu_channel_host_factory.cc +++ b/content/browser/gpu/browser_gpu_channel_host_factory.cc @@ -11,7 +11,7 @@ #include "content/browser/gpu/gpu_process_host.h" #include "content/browser/gpu/gpu_surface_tracker.h" #include "content/common/child_process_host_impl.h" -#include "content/common/gpu/client/gpu_memory_buffer_impl.h" +#include "content/common/gpu/client/gpu_memory_buffer_impl_shm.h" #include "content/common/gpu/gpu_messages.h" #include "content/public/browser/browser_thread.h" #include "content/public/common/content_client.h" @@ -380,11 +380,12 @@ scoped_ptr<gfx::GpuMemoryBuffer> if (!shm->CreateAnonymous(size)) return scoped_ptr<gfx::GpuMemoryBuffer>(); - return make_scoped_ptr<gfx::GpuMemoryBuffer>( - new GpuMemoryBufferImpl(shm.Pass(), - width, - height, - internalformat)); + scoped_ptr<GpuMemoryBufferImplShm> buffer( + new GpuMemoryBufferImplShm(gfx::Size(width, height), internalformat)); + if (!buffer->InitializeFromSharedMemory(shm.Pass())) + return scoped_ptr<gfx::GpuMemoryBuffer>(); + + return buffer.PassAs<gfx::GpuMemoryBuffer>(); } // static diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc index 10a3901..d7962cd 100644 --- a/content/browser/renderer_host/render_message_filter.cc +++ b/content/browser/renderer_host/render_message_filter.cc @@ -33,6 +33,7 @@ #include "content/common/child_process_messages.h" #include "content/common/cookie_data.h" #include "content/common/desktop_notification_messages.h" +#include "content/common/gpu/client/gpu_memory_buffer_impl.h" #include "content/common/media/media_param_traits.h" #include "content/common/view_messages.h" #include "content/public/browser/browser_child_process_host.h" @@ -68,7 +69,9 @@ #include "ui/gfx/color_profile.h" #if defined(OS_MACOSX) +#include "content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h" #include "content/common/mac/font_descriptor.h" +#include "ui/gl/io_surface_support_mac.h" #else #include "gpu/GLES2/gl2extchromium.h" #include "third_party/khronos/GLES2/gl2.h" @@ -204,6 +207,23 @@ class OpenChannelToPpapiBrokerCallback int routing_id_; }; +#if defined(OS_MACOSX) +void AddBooleanValue(CFMutableDictionaryRef dictionary, + const CFStringRef key, + bool value) { + CFDictionaryAddValue( + dictionary, key, value ? kCFBooleanTrue : kCFBooleanFalse); +} + +void AddIntegerValue(CFMutableDictionaryRef dictionary, + const CFStringRef key, + int32 value) { + base::ScopedCFTypeRef<CFNumberRef> number( + CFNumberCreate(NULL, kCFNumberSInt32Type, &value)); + CFDictionaryAddValue(dictionary, key, number.get()); +} +#endif + } // namespace class RenderMessageFilter::OpenChannelToNpapiPluginCallback @@ -1156,21 +1176,78 @@ void RenderMessageFilter::OnWebAudioMediaCodec( #endif void RenderMessageFilter::OnAllocateGpuMemoryBuffer( - uint32 buffer_size, + uint32 width, + uint32 height, + uint32 internalformat, 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. + if (!GpuMemoryBufferImpl::IsFormatValid(internalformat)) { + handle->type = gfx::EMPTY_BUFFER; + return; + } + +#if defined(OS_MACOSX) + if (GpuMemoryBufferImplIOSurface::IsFormatSupported(internalformat)) { + IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize(); + if (io_surface_support) { + base::ScopedCFTypeRef<CFMutableDictionaryRef> properties; + properties.reset( + CFDictionaryCreateMutable(kCFAllocatorDefault, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks)); + AddIntegerValue(properties, + io_surface_support->GetKIOSurfaceWidth(), + width); + AddIntegerValue(properties, + io_surface_support->GetKIOSurfaceHeight(), + height); + AddIntegerValue(properties, + io_surface_support->GetKIOSurfaceBytesPerElement(), + GpuMemoryBufferImpl::BytesPerPixel(internalformat)); + AddIntegerValue(properties, + io_surface_support->GetKIOSurfacePixelFormat(), + GpuMemoryBufferImplIOSurface::PixelFormat( + internalformat)); + // TODO(reveman): Remove this when using a mach_port_t to transfer + // IOSurface to renderer process. crbug.com/323304 + AddBooleanValue(properties, + io_surface_support->GetKIOSurfaceIsGlobal(), + true); + + base::ScopedCFTypeRef<CFTypeRef> io_surface( + io_surface_support->IOSurfaceCreate(properties)); + if (io_surface) { + handle->type = gfx::IO_SURFACE_BUFFER; + handle->io_surface_id = io_surface_support->IOSurfaceGetID(io_surface); + + // TODO(reveman): This makes the assumption that the renderer will + // grab a reference to the surface before sending another message. + // crbug.com/325045 + last_io_surface_ = io_surface; + return; + } + } + } +#endif + + uint64 stride = static_cast<uint64>(width) * + GpuMemoryBufferImpl::BytesPerPixel(internalformat); + if (stride > std::numeric_limits<uint32>::max()) { + handle->type = gfx::EMPTY_BUFFER; + return; + } + + uint64 buffer_size = stride * static_cast<uint64>(height); + if (buffer_size > std::numeric_limits<size_t>::max()) { + handle->type = gfx::EMPTY_BUFFER; + return; + } + + // Fallback to fake GpuMemoryBuffer that is backed by shared memory and + // requires an upload before it can be used as a texture. handle->type = gfx::SHARED_MEMORY_BUFFER; ChildProcessHostImpl::AllocateSharedMemory( - buffer_size, PeerHandle(), &handle->handle); + static_cast<size_t>(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 23483a4..d423901 100644 --- a/content/browser/renderer_host/render_message_filter.h +++ b/content/browser/renderer_host/render_message_filter.h @@ -30,6 +30,7 @@ #include "ui/surface/transport_dib.h" #if defined(OS_MACOSX) +#include "base/mac/scoped_cftyperef.h" #include "content/common/mac/font_loader.h" #endif @@ -259,7 +260,9 @@ class RenderMessageFilter : public BrowserMessageFilter { uint32_t data_size); #endif - void OnAllocateGpuMemoryBuffer(uint32 buffer_size, + void OnAllocateGpuMemoryBuffer(uint32 width, + uint32 height, + uint32 internalformat, gfx::GpuMemoryBufferHandle* handle); // Cached resource request dispatcher host and plugin service, guaranteed to @@ -302,6 +305,10 @@ class RenderMessageFilter : public BrowserMessageFilter { media::AudioManager* audio_manager_; MediaInternals* media_internals_; +#if defined(OS_MACOSX) + base::ScopedCFTypeRef<CFTypeRef> last_io_surface_; +#endif + DISALLOW_COPY_AND_ASSIGN(RenderMessageFilter); }; diff --git a/content/common/child_process_host_impl.cc b/content/common/child_process_host_impl.cc index a2f40d4..1467536 100644 --- a/content/common/child_process_host_impl.cc +++ b/content/common/child_process_host_impl.cc @@ -17,6 +17,7 @@ #include "base/strings/stringprintf.h" #include "base/third_party/dynamic_annotations/dynamic_annotations.h" #include "content/common/child_process_messages.h" +#include "content/common/gpu/client/gpu_memory_buffer_impl.h" #include "content/public/common/child_process_host_delegate.h" #include "content/public/common/content_paths.h" #include "content/public/common/content_switches.h" @@ -296,10 +297,15 @@ void ChildProcessHostImpl::OnShutdownRequest() { } void ChildProcessHostImpl::OnAllocateGpuMemoryBuffer( - uint32 buffer_size, + uint32 width, + uint32 height, + uint32 internalformat, gfx::GpuMemoryBufferHandle* handle) { handle->type = gfx::SHARED_MEMORY_BUFFER; - AllocateSharedMemory(buffer_size, peer_handle_, &handle->handle); + AllocateSharedMemory( + width * height * GpuMemoryBufferImpl::BytesPerPixel(internalformat), + 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 74700bc..e0e4bbf 100644 --- a/content/common/child_process_host_impl.h +++ b/content/common/child_process_host_impl.h @@ -79,7 +79,9 @@ class CONTENT_EXPORT ChildProcessHostImpl : public ChildProcessHost, void OnShutdownRequest(); void OnAllocateSharedMemory(uint32 buffer_size, base::SharedMemoryHandle* handle); - void OnAllocateGpuMemoryBuffer(uint32 buffer_size, + void OnAllocateGpuMemoryBuffer(uint32 width, + uint32 height, + uint32 internalformat, gfx::GpuMemoryBufferHandle* handle); ChildProcessHostDelegate* delegate_; diff --git a/content/common/child_process_messages.h b/content/common/child_process_messages.h index c122588..7c1dce5 100644 --- a/content/common/child_process_messages.h +++ b/content/common/child_process_messages.h @@ -60,6 +60,9 @@ IPC_ENUM_TRAITS(gfx::GpuMemoryBufferType) IPC_STRUCT_TRAITS_BEGIN(gfx::GpuMemoryBufferHandle) IPC_STRUCT_TRAITS_MEMBER(type) IPC_STRUCT_TRAITS_MEMBER(handle) +#if defined(OS_MACOSX) + IPC_STRUCT_TRAITS_MEMBER(io_surface_id) +#endif IPC_STRUCT_TRAITS_END() #undef IPC_MESSAGE_EXPORT @@ -148,6 +151,8 @@ IPC_MESSAGE_CONTROL1(ChildProcessHostMsg_TcmallocStats, #endif // Asks the browser to create a gpu memory buffer. -IPC_SYNC_MESSAGE_CONTROL1_1(ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer, - uint32 /* buffer size */, +IPC_SYNC_MESSAGE_CONTROL3_1(ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer, + uint32 /* width */, + uint32 /* height */, + uint32 /* internalformat */, gfx::GpuMemoryBufferHandle) diff --git a/content/common/gpu/client/gpu_channel_host.cc b/content/common/gpu/client/gpu_channel_host.cc index faaa3e8..705f4b9d 100644 --- a/content/common/gpu/client/gpu_channel_host.cc +++ b/content/common/gpu/client/gpu_channel_host.cc @@ -50,6 +50,9 @@ bool GpuChannelHost::IsValidGpuMemoryBuffer( gfx::GpuMemoryBufferHandle handle) { switch (handle.type) { case gfx::SHARED_MEMORY_BUFFER: +#if defined(OS_MACOSX) + case gfx::IO_SURFACE_BUFFER: +#endif return true; default: return false; @@ -303,6 +306,10 @@ gfx::GpuMemoryBufferHandle GpuChannelHost::ShareGpuMemoryBufferToGpuProcess( handle.handle = ShareToGpuProcess(source_handle.handle); return handle; } +#if defined(OS_MACOSX) + case gfx::IO_SURFACE_BUFFER: + return source_handle; +#endif default: NOTREACHED(); return gfx::GpuMemoryBufferHandle(); diff --git a/content/common/gpu/client/gpu_memory_buffer_impl.cc b/content/common/gpu/client/gpu_memory_buffer_impl.cc index e27e260..c469a07 100644 --- a/content/common/gpu/client/gpu_memory_buffer_impl.cc +++ b/content/common/gpu/client/gpu_memory_buffer_impl.cc @@ -9,51 +9,16 @@ 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)), + gfx::Size size, unsigned internalformat) + : size_(size), 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) { switch (internalformat) { @@ -77,4 +42,12 @@ size_t GpuMemoryBufferImpl::BytesPerPixel(unsigned internalformat) { } } +bool GpuMemoryBufferImpl::IsMapped() const { + return mapped_; +} + +uint32 GpuMemoryBufferImpl::GetStride() const { + return size_.width() * BytesPerPixel(internalformat_); +} + } // namespace content diff --git a/content/common/gpu/client/gpu_memory_buffer_impl.h b/content/common/gpu/client/gpu_memory_buffer_impl.h index 3858c3f..ee85f0f 100644 --- a/content/common/gpu/client/gpu_memory_buffer_impl.h +++ b/content/common/gpu/client/gpu_memory_buffer_impl.h @@ -11,28 +11,26 @@ namespace content { -// Provides common implementation of a GPU memory buffer based -// on a shared memory handle. +// Provides common implementation of a GPU memory buffer. class GpuMemoryBufferImpl : public gfx::GpuMemoryBuffer { public: - GpuMemoryBufferImpl(scoped_ptr<base::SharedMemory> shared_memory, - size_t width, - size_t height, - unsigned internalformat); + static scoped_ptr<GpuMemoryBufferImpl> Create( + gfx::GpuMemoryBufferHandle handle, + gfx::Size size, + unsigned internalformat); + virtual ~GpuMemoryBufferImpl(); + static bool IsFormatValid(unsigned internalformat); + static size_t BytesPerPixel(unsigned internalformat); + // 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); + protected: + GpuMemoryBufferImpl(gfx::Size size, unsigned internalformat); - private: - scoped_ptr<base::SharedMemory> shared_memory_; const gfx::Size size_; unsigned internalformat_; bool mapped_; diff --git a/content/common/gpu/client/gpu_memory_buffer_impl_android.cc b/content/common/gpu/client/gpu_memory_buffer_impl_android.cc new file mode 100644 index 0000000..ffd4e38 --- /dev/null +++ b/content/common/gpu/client/gpu_memory_buffer_impl_android.cc @@ -0,0 +1,29 @@ +// 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 "content/common/gpu/client/gpu_memory_buffer_impl_shm.h" + +namespace content { + +scoped_ptr<GpuMemoryBufferImpl> GpuMemoryBufferImpl::Create( + gfx::GpuMemoryBufferHandle handle, + gfx::Size size, + unsigned internalformat) { + switch (handle.type) { + case gfx::SHARED_MEMORY_BUFFER: { + scoped_ptr<GpuMemoryBufferImplShm> buffer( + new GpuMemoryBufferImplShm(size, internalformat)); + if (!buffer->Initialize(handle)) + return scoped_ptr<GpuMemoryBufferImpl>(); + + return buffer.PassAs<GpuMemoryBufferImpl>(); + } + default: + return scoped_ptr<GpuMemoryBufferImpl>(); + } +} + +} // namespace content diff --git a/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.cc b/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.cc new file mode 100644 index 0000000..abc9907 --- /dev/null +++ b/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.cc @@ -0,0 +1,79 @@ +// 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_io_surface.h" + +#include "base/logging.h" +#include "ui/gl/gl_bindings.h" +#include "ui/gl/io_surface_support_mac.h" + +namespace content { + +GpuMemoryBufferImplIOSurface::GpuMemoryBufferImplIOSurface( + gfx::Size size, unsigned internalformat) + : GpuMemoryBufferImpl(size, internalformat), + io_surface_support_(IOSurfaceSupport::Initialize()) { + CHECK(io_surface_support_); +} + +GpuMemoryBufferImplIOSurface::~GpuMemoryBufferImplIOSurface() { +} + +// static +bool GpuMemoryBufferImplIOSurface::IsFormatSupported(unsigned internalformat) { + switch (internalformat) { + case GL_BGRA8_EXT: + return true; + default: + return false; + } +} + +// static +uint32 GpuMemoryBufferImplIOSurface::PixelFormat(unsigned internalformat) { + switch (internalformat) { + case GL_BGRA8_EXT: + return 'BGRA'; + default: + NOTREACHED(); + return 0; + } +} + +bool GpuMemoryBufferImplIOSurface::Initialize( + gfx::GpuMemoryBufferHandle handle) { + io_surface_.reset(io_surface_support_->IOSurfaceLookup(handle.io_surface_id)); + if (!io_surface_) { + VLOG(1) << "IOSurface lookup failed"; + return false; + } + + return true; +} + +void GpuMemoryBufferImplIOSurface::Map(AccessMode mode, void** vaddr) { + DCHECK(!mapped_); + io_surface_support_->IOSurfaceLock(io_surface_, 0, NULL); + *vaddr = io_surface_support_->IOSurfaceGetBaseAddress(io_surface_); + mapped_ = true; +} + +void GpuMemoryBufferImplIOSurface::Unmap() { + DCHECK(mapped_); + io_surface_support_->IOSurfaceUnlock(io_surface_, 0, NULL); + mapped_ = false; +} + +uint32 GpuMemoryBufferImplIOSurface::GetStride() const { + return io_surface_support_->IOSurfaceGetBytesPerRow(io_surface_); +} + +gfx::GpuMemoryBufferHandle GpuMemoryBufferImplIOSurface::GetHandle() const { + gfx::GpuMemoryBufferHandle handle; + handle.type = gfx::IO_SURFACE_BUFFER; + handle.io_surface_id = io_surface_support_->IOSurfaceGetID(io_surface_); + return handle; +} + +} // namespace content diff --git a/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h b/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h new file mode 100644 index 0000000..da2936a --- /dev/null +++ b/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h @@ -0,0 +1,42 @@ +// 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_IO_SURFACE_H_ +#define CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_IO_SURFACE_H_ + +#include "base/mac/scoped_cftyperef.h" +#include "content/common/gpu/client/gpu_memory_buffer_impl.h" + +class IOSurfaceSupport; + +namespace content { + +// Provides implementation of a GPU memory buffer based +// on an IO surface handle. +class GpuMemoryBufferImplIOSurface : public GpuMemoryBufferImpl { + public: + GpuMemoryBufferImplIOSurface(gfx::Size size, unsigned internalformat); + virtual ~GpuMemoryBufferImplIOSurface(); + + static bool IsFormatSupported(unsigned internalformat); + static uint32 PixelFormat(unsigned internalformat); + + bool Initialize(gfx::GpuMemoryBufferHandle handle); + + // Overridden from gfx::GpuMemoryBuffer: + virtual void Map(AccessMode mode, void** vaddr) OVERRIDE; + virtual void Unmap() OVERRIDE; + virtual uint32 GetStride() const OVERRIDE; + virtual gfx::GpuMemoryBufferHandle GetHandle() const OVERRIDE; + + private: + IOSurfaceSupport* io_surface_support_; + base::ScopedCFTypeRef<CFTypeRef> io_surface_; + + DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferImplIOSurface); +}; + +} // namespace content + +#endif // CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_IO_SURFACE_H_ diff --git a/content/common/gpu/client/gpu_memory_buffer_impl_linux.cc b/content/common/gpu/client/gpu_memory_buffer_impl_linux.cc new file mode 100644 index 0000000..ffd4e38 --- /dev/null +++ b/content/common/gpu/client/gpu_memory_buffer_impl_linux.cc @@ -0,0 +1,29 @@ +// 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 "content/common/gpu/client/gpu_memory_buffer_impl_shm.h" + +namespace content { + +scoped_ptr<GpuMemoryBufferImpl> GpuMemoryBufferImpl::Create( + gfx::GpuMemoryBufferHandle handle, + gfx::Size size, + unsigned internalformat) { + switch (handle.type) { + case gfx::SHARED_MEMORY_BUFFER: { + scoped_ptr<GpuMemoryBufferImplShm> buffer( + new GpuMemoryBufferImplShm(size, internalformat)); + if (!buffer->Initialize(handle)) + return scoped_ptr<GpuMemoryBufferImpl>(); + + return buffer.PassAs<GpuMemoryBufferImpl>(); + } + default: + return scoped_ptr<GpuMemoryBufferImpl>(); + } +} + +} // namespace content diff --git a/content/common/gpu/client/gpu_memory_buffer_impl_mac.cc b/content/common/gpu/client/gpu_memory_buffer_impl_mac.cc new file mode 100644 index 0000000..1c8e552 --- /dev/null +++ b/content/common/gpu/client/gpu_memory_buffer_impl_mac.cc @@ -0,0 +1,38 @@ +// 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 "content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h" +#include "content/common/gpu/client/gpu_memory_buffer_impl_shm.h" + +namespace content { + +scoped_ptr<GpuMemoryBufferImpl> GpuMemoryBufferImpl::Create( + gfx::GpuMemoryBufferHandle handle, + gfx::Size size, + unsigned internalformat) { + switch (handle.type) { + case gfx::SHARED_MEMORY_BUFFER: { + scoped_ptr<GpuMemoryBufferImplShm> buffer( + new GpuMemoryBufferImplShm(size, internalformat)); + if (!buffer->Initialize(handle)) + return scoped_ptr<GpuMemoryBufferImpl>(); + + return buffer.PassAs<GpuMemoryBufferImpl>(); + } + case gfx::IO_SURFACE_BUFFER: { + scoped_ptr<GpuMemoryBufferImplIOSurface> buffer( + new GpuMemoryBufferImplIOSurface(size, internalformat)); + if (!buffer->Initialize(handle)) + return scoped_ptr<GpuMemoryBufferImpl>(); + + return buffer.PassAs<GpuMemoryBufferImpl>(); + } + default: + return scoped_ptr<GpuMemoryBufferImpl>(); + } +} + +} // namespace content diff --git a/content/common/gpu/client/gpu_memory_buffer_impl_ozone.cc b/content/common/gpu/client/gpu_memory_buffer_impl_ozone.cc new file mode 100644 index 0000000..ffd4e38 --- /dev/null +++ b/content/common/gpu/client/gpu_memory_buffer_impl_ozone.cc @@ -0,0 +1,29 @@ +// 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 "content/common/gpu/client/gpu_memory_buffer_impl_shm.h" + +namespace content { + +scoped_ptr<GpuMemoryBufferImpl> GpuMemoryBufferImpl::Create( + gfx::GpuMemoryBufferHandle handle, + gfx::Size size, + unsigned internalformat) { + switch (handle.type) { + case gfx::SHARED_MEMORY_BUFFER: { + scoped_ptr<GpuMemoryBufferImplShm> buffer( + new GpuMemoryBufferImplShm(size, internalformat)); + if (!buffer->Initialize(handle)) + return scoped_ptr<GpuMemoryBufferImpl>(); + + return buffer.PassAs<GpuMemoryBufferImpl>(); + } + default: + return scoped_ptr<GpuMemoryBufferImpl>(); + } +} + +} // namespace content diff --git a/content/common/gpu/client/gpu_memory_buffer_impl_shm.cc b/content/common/gpu/client/gpu_memory_buffer_impl_shm.cc new file mode 100644 index 0000000..7af4452 --- /dev/null +++ b/content/common/gpu/client/gpu_memory_buffer_impl_shm.cc @@ -0,0 +1,56 @@ +// 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_shm.h" + +#include "base/logging.h" + +namespace content { + +GpuMemoryBufferImplShm::GpuMemoryBufferImplShm( + gfx::Size size, unsigned internalformat) + : GpuMemoryBufferImpl(size, internalformat) { +} + +GpuMemoryBufferImplShm::~GpuMemoryBufferImplShm() { +} + +bool GpuMemoryBufferImplShm::Initialize(gfx::GpuMemoryBufferHandle handle) { + if (!base::SharedMemory::IsHandleValid(handle.handle)) + return false; + shared_memory_.reset(new base::SharedMemory(handle.handle, false)); + DCHECK(!shared_memory_->memory()); + return true; +} + +bool GpuMemoryBufferImplShm::InitializeFromSharedMemory( + scoped_ptr<base::SharedMemory> shared_memory) { + shared_memory_ = shared_memory.Pass(); + DCHECK(!shared_memory_->memory()); + return true; +} + +void GpuMemoryBufferImplShm::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 GpuMemoryBufferImplShm::Unmap() { + DCHECK(mapped_); + shared_memory_->Unmap(); + mapped_ = false; +} + +gfx::GpuMemoryBufferHandle GpuMemoryBufferImplShm::GetHandle() const { + gfx::GpuMemoryBufferHandle handle; + handle.type = gfx::SHARED_MEMORY_BUFFER; + handle.handle = shared_memory_->handle(); + return handle; +} + +} // namespace content diff --git a/content/common/gpu/client/gpu_memory_buffer_impl_shm.h b/content/common/gpu/client/gpu_memory_buffer_impl_shm.h new file mode 100644 index 0000000..be86aab --- /dev/null +++ b/content/common/gpu/client/gpu_memory_buffer_impl_shm.h @@ -0,0 +1,36 @@ +// 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_SHM_H_ +#define CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_SHM_H_ + +#include "content/common/gpu/client/gpu_memory_buffer_impl.h" + +namespace content { + +// Provides implementation of a GPU memory buffer based +// on a shared memory handle. +class GpuMemoryBufferImplShm : public GpuMemoryBufferImpl { + public: + GpuMemoryBufferImplShm(gfx::Size size, unsigned internalformat); + virtual ~GpuMemoryBufferImplShm(); + + bool Initialize(gfx::GpuMemoryBufferHandle handle); + bool InitializeFromSharedMemory( + scoped_ptr<base::SharedMemory> shared_memory); + + // Overridden from gfx::GpuMemoryBuffer: + virtual void Map(AccessMode mode, void** vaddr) OVERRIDE; + virtual void Unmap() OVERRIDE; + virtual gfx::GpuMemoryBufferHandle GetHandle() const OVERRIDE; + + private: + scoped_ptr<base::SharedMemory> shared_memory_; + + DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferImplShm); +}; + +} // namespace content + +#endif // CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_SHM_H_ diff --git a/content/common/gpu/client/gpu_memory_buffer_impl_win.cc b/content/common/gpu/client/gpu_memory_buffer_impl_win.cc new file mode 100644 index 0000000..ffd4e38 --- /dev/null +++ b/content/common/gpu/client/gpu_memory_buffer_impl_win.cc @@ -0,0 +1,29 @@ +// 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 "content/common/gpu/client/gpu_memory_buffer_impl_shm.h" + +namespace content { + +scoped_ptr<GpuMemoryBufferImpl> GpuMemoryBufferImpl::Create( + gfx::GpuMemoryBufferHandle handle, + gfx::Size size, + unsigned internalformat) { + switch (handle.type) { + case gfx::SHARED_MEMORY_BUFFER: { + scoped_ptr<GpuMemoryBufferImplShm> buffer( + new GpuMemoryBufferImplShm(size, internalformat)); + if (!buffer->Initialize(handle)) + return scoped_ptr<GpuMemoryBufferImpl>(); + + return buffer.PassAs<GpuMemoryBufferImpl>(); + } + default: + return scoped_ptr<GpuMemoryBufferImpl>(); + } +} + +} // namespace content diff --git a/content/common/sandbox_mac.mm b/content/common/sandbox_mac.mm index a9f42e2..0baa275 100644 --- a/content/common/sandbox_mac.mm +++ b/content/common/sandbox_mac.mm @@ -36,6 +36,7 @@ extern "C" { #include "third_party/icu/source/common/unicode/uchar.h" #include "ui/base/layout.h" #include "ui/gl/gl_surface.h" +#include "ui/gl/io_surface_support_mac.h" namespace content { namespace { @@ -307,6 +308,15 @@ void Sandbox::SandboxWarmup(int sandbox_type) { base::GetUrandomFD(); } + { // IOSurfaceLookup() - 10.7 + // Needed by zero-copy texture update framework - crbug.com/323338 + IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize(); + if (io_surface_support) { + base::ScopedCFTypeRef<CFTypeRef> io_surface( + io_surface_support->IOSurfaceLookup(0)); + } + } + // Process-type dependent warm-up. if (sandbox_type == SANDBOX_TYPE_UTILITY) { // CFTimeZoneCopyZone() tries to read /etc and /private/etc/localtime - 10.8 diff --git a/content/content_common.gypi b/content/content_common.gypi index 9434052..7499b90 100644 --- a/content/content_common.gypi +++ b/content/content_common.gypi @@ -198,6 +198,13 @@ '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_memory_buffer_impl_android.cc', + 'common/gpu/client/gpu_memory_buffer_impl_linux.cc', + 'common/gpu/client/gpu_memory_buffer_impl_mac.cc', + 'common/gpu/client/gpu_memory_buffer_impl_ozone.cc', + 'common/gpu/client/gpu_memory_buffer_impl_shm.cc', + 'common/gpu/client/gpu_memory_buffer_impl_shm.h', + 'common/gpu/client/gpu_memory_buffer_impl_win.cc', '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', @@ -442,6 +449,10 @@ ], }], ['OS=="mac"', { + 'sources': [ + 'common/gpu/client/gpu_memory_buffer_impl_io_surface.cc', + 'common/gpu/client/gpu_memory_buffer_impl_io_surface.h', + ], 'sources!': [ 'common/plugin_list_posix.cc', ], diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 15c26a9..56a15b0 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc @@ -406,6 +406,10 @@ void RenderThreadImpl::Init() { renderer_process_id_ = base::kNullProcessId; + // AllocateGpuMemoryBuffer must be used exclusively on one thread but + // it doesn't have to be the same thread RenderThreadImpl is created on. + allocate_gpu_memory_buffer_thread_checker_.DetachFromThread(); + TRACE_EVENT_END_ETW("RenderThreadImpl::Init", 0, ""); } @@ -1074,18 +1078,18 @@ scoped_ptr<gfx::GpuMemoryBuffer> RenderThreadImpl::AllocateGpuMemoryBuffer( size_t width, size_t height, unsigned internalformat) { - if (!GpuMemoryBufferImpl::IsFormatValid(internalformat)) - return scoped_ptr<gfx::GpuMemoryBuffer>(); + DCHECK(allocate_gpu_memory_buffer_thread_checker_.CalledOnValidThread()); - size_t size = width * height * - GpuMemoryBufferImpl::BytesPerPixel(internalformat); - if (size > static_cast<size_t>(std::numeric_limits<int>::max())) + if (!GpuMemoryBufferImpl::IsFormatValid(internalformat)) return scoped_ptr<gfx::GpuMemoryBuffer>(); gfx::GpuMemoryBufferHandle handle; bool success; IPC::Message* message = - new ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer(size, &handle); + new ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer(width, + height, + internalformat, + &handle); // Allow calling this from the compositor thread. if (base::MessageLoop::current() == message_loop()) @@ -1096,19 +1100,10 @@ scoped_ptr<gfx::GpuMemoryBuffer> RenderThreadImpl::AllocateGpuMemoryBuffer( 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)); + return GpuMemoryBufferImpl::Create( + handle, + gfx::Size(width, height), + internalformat).PassAs<gfx::GpuMemoryBuffer>(); } void RenderThreadImpl::DoNotSuspendWebKitSharedTimer() { diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index 73981fc..5dffc8d 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h @@ -13,6 +13,7 @@ #include "base/observer_list.h" #include "base/process/process_handle.h" #include "base/strings/string16.h" +#include "base/threading/thread_checker.h" #include "base/timer/timer.h" #include "build/build_config.h" #include "content/child/child_thread.h" @@ -506,6 +507,11 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread, base::ProcessId renderer_process_id_; + // TODO(reveman): Allow AllocateGpuMemoryBuffer to be called from + // multiple threads. Current allocation mechanism for IOSurface + // backed GpuMemoryBuffers prevent this. crbug.com/325045 + base::ThreadChecker allocate_gpu_memory_buffer_thread_checker_; + DISALLOW_COPY_AND_ASSIGN(RenderThreadImpl); }; diff --git a/ui/gfx/gpu_memory_buffer.h b/ui/gfx/gpu_memory_buffer.h index 17bb669..4a7b142 100644 --- a/ui/gfx/gpu_memory_buffer.h +++ b/ui/gfx/gpu_memory_buffer.h @@ -18,7 +18,8 @@ namespace gfx { enum GpuMemoryBufferType { EMPTY_BUFFER, SHARED_MEMORY_BUFFER, - EGL_CLIENT_BUFFER + EGL_CLIENT_BUFFER, + IO_SURFACE_BUFFER }; struct GpuMemoryBufferHandle { @@ -28,6 +29,9 @@ struct GpuMemoryBufferHandle { #if defined(OS_ANDROID) , native_buffer(NULL) #endif +#if defined(OS_MACOSX) + , io_surface_id(0) +#endif { } bool is_null() const { return type == EMPTY_BUFFER; } @@ -36,6 +40,10 @@ struct GpuMemoryBufferHandle { #if defined(OS_ANDROID) EGLClientBuffer native_buffer; #endif +#if defined(OS_MACOSX) + uint32 io_surface_id; +#endif + }; // Interface for creating and accessing a zero-copy GPU memory buffer. diff --git a/ui/gl/gl.gyp b/ui/gl/gl.gyp index 4aa5f70..da89782 100644 --- a/ui/gl/gl.gyp +++ b/ui/gl/gl.gyp @@ -254,6 +254,8 @@ 'sources': [ 'gl_context_cgl.cc', 'gl_context_cgl.h', + 'gl_image_io_surface.cc', + 'gl_image_io_surface.h', 'gl_surface_cgl.cc', 'gl_surface_cgl.h', 'gl_context_nsview.mm', diff --git a/ui/gl/gl_image_io_surface.cc b/ui/gl/gl_image_io_surface.cc new file mode 100644 index 0000000..23a7777 --- /dev/null +++ b/ui/gl/gl_image_io_surface.cc @@ -0,0 +1,79 @@ +// 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 "ui/gl/gl_image_io_surface.h" + +#include "ui/gl/gl_bindings.h" +#include "ui/gl/gl_context.h" +#include "ui/gl/io_surface_support_mac.h" + +namespace gfx { + +GLImageIOSurface::GLImageIOSurface(gfx::Size size) + : io_surface_support_(IOSurfaceSupport::Initialize()), + size_(size) { + CHECK(io_surface_support_); +} + +GLImageIOSurface::~GLImageIOSurface() { + Destroy(); +} + +bool GLImageIOSurface::Initialize(gfx::GpuMemoryBufferHandle buffer) { + io_surface_.reset(io_surface_support_->IOSurfaceLookup(buffer.io_surface_id)); + if (!io_surface_) { + LOG(ERROR) << "IOSurface lookup failed"; + return false; + } + + return true; +} + +void GLImageIOSurface::Destroy() { +} + +gfx::Size GLImageIOSurface::GetSize() { + return size_; +} + +bool GLImageIOSurface::BindTexImage(unsigned target) { + if (target != GL_TEXTURE_RECTANGLE_ARB) { + // This might be supported in the future. For now, perform strict + // validation so we know what's going on. + LOG(ERROR) << "IOSurface requires TEXTURE_RECTANGLE_ARB target"; + return false; + } + + CGLContextObj cgl_context = static_cast<CGLContextObj>( + GLContext::GetCurrent()->GetHandle()); + + DCHECK(io_surface_); + CGLError cgl_error = io_surface_support_->CGLTexImageIOSurface2D( + cgl_context, + target, + GL_RGBA, + size_.width(), + size_.height(), + GL_BGRA, + GL_UNSIGNED_INT_8_8_8_8_REV, + io_surface_.get(), + 0); + if (cgl_error != kCGLNoError) { + LOG(ERROR) << "Error in CGLTexImageIOSurface2D"; + return false; + } + + return true; +} + +void GLImageIOSurface::ReleaseTexImage(unsigned target) { +} + +void GLImageIOSurface::WillUseTexImage() { +} + +void GLImageIOSurface::DidUseTexImage() { +} + +} // namespace gfx diff --git a/ui/gl/gl_image_io_surface.h b/ui/gl/gl_image_io_surface.h new file mode 100644 index 0000000..1770982 --- /dev/null +++ b/ui/gl/gl_image_io_surface.h @@ -0,0 +1,42 @@ +// 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 UI_GL_GL_IMAGE_IO_SURFACE_H_ +#define UI_GL_GL_IMAGE_IO_SURFACE_H_ + +#include "base/mac/scoped_cftyperef.h" +#include "ui/gl/gl_image.h" + +class IOSurfaceSupport; + +namespace gfx { + +class GL_EXPORT GLImageIOSurface : public GLImage { + public: + explicit GLImageIOSurface(gfx::Size size); + + bool Initialize(gfx::GpuMemoryBufferHandle buffer); + + // Implement GLImage. + virtual void Destroy() OVERRIDE; + virtual gfx::Size GetSize() OVERRIDE; + virtual bool BindTexImage(unsigned target) OVERRIDE; + virtual void ReleaseTexImage(unsigned target) OVERRIDE; + virtual void WillUseTexImage() OVERRIDE; + virtual void DidUseTexImage() OVERRIDE; + + protected: + virtual ~GLImageIOSurface(); + + private: + IOSurfaceSupport* io_surface_support_; + base::ScopedCFTypeRef<CFTypeRef> io_surface_; + gfx::Size size_; + + DISALLOW_COPY_AND_ASSIGN(GLImageIOSurface); +}; + +} // namespace gfx + +#endif // UI_GL_GL_IMAGE_IO_SURFACE_H_ diff --git a/ui/gl/gl_image_mac.cc b/ui/gl/gl_image_mac.cc index 04dc61e..a48047f 100644 --- a/ui/gl/gl_image_mac.cc +++ b/ui/gl/gl_image_mac.cc @@ -5,6 +5,7 @@ #include "ui/gl/gl_image.h" #include "base/debug/trace_event.h" +#include "ui/gl/gl_image_io_surface.h" #include "ui/gl/gl_image_shm.h" #include "ui/gl/gl_image_stub.h" #include "ui/gl/gl_implementation.h" @@ -44,6 +45,13 @@ scoped_refptr<GLImage> GLImage::CreateGLImageForGpuMemoryBuffer( return image; } + case IO_SURFACE_BUFFER: { + scoped_refptr<GLImageIOSurface> image(new GLImageIOSurface(size)); + if (!image->Initialize(buffer)) + return NULL; + + return image; + } default: NOTREACHED(); return NULL; diff --git a/ui/gl/io_surface_support_mac.cc b/ui/gl/io_surface_support_mac.cc index 077eb81..a7aeae8 100644 --- a/ui/gl/io_surface_support_mac.cc +++ b/ui/gl/io_surface_support_mac.cc @@ -14,6 +14,15 @@ typedef mach_port_t (*IOSurfaceCreateMachPortProcPtr)(CFTypeRef io_surface); typedef CFTypeRef (*IOSurfaceLookupFromMachPortProcPtr)(mach_port_t port); typedef size_t (*IOSurfaceGetWidthPtr)(CFTypeRef io_surface); typedef size_t (*IOSurfaceGetHeightPtr)(CFTypeRef io_surface); +typedef size_t (*IOSurfaceGetBytesPerRowPtr)(CFTypeRef io_surface); +typedef void* (*IOSurfaceGetBaseAddressPtr)(CFTypeRef io_surface); +typedef IOReturn (*IOSurfaceLockPtr)(CFTypeRef io_surface, + uint32 options, + uint32* seed); +typedef IOReturn (*IOSurfaceUnlockPtr)(CFTypeRef io_surface, + uint32 options, + uint32* seed); + typedef CGLError (*CGLTexImageIOSurface2DProcPtr)(CGLContextObj ctx, GLenum target, GLenum internal_format, @@ -37,6 +46,7 @@ class IOSurfaceSupportImpl : public IOSurfaceSupport { virtual CFStringRef GetKIOSurfaceWidth() OVERRIDE; virtual CFStringRef GetKIOSurfaceHeight() OVERRIDE; virtual CFStringRef GetKIOSurfaceBytesPerElement() OVERRIDE; + virtual CFStringRef GetKIOSurfacePixelFormat() OVERRIDE; virtual CFStringRef GetKIOSurfaceIsGlobal() OVERRIDE; virtual CFTypeRef IOSurfaceCreate(CFDictionaryRef properties) OVERRIDE; @@ -47,6 +57,15 @@ class IOSurfaceSupportImpl : public IOSurfaceSupport { virtual size_t IOSurfaceGetWidth(CFTypeRef io_surface) OVERRIDE; virtual size_t IOSurfaceGetHeight(CFTypeRef io_surface) OVERRIDE; + virtual size_t IOSurfaceGetBytesPerRow(CFTypeRef io_surface) OVERRIDE; + virtual void* IOSurfaceGetBaseAddress(CFTypeRef io_surface) OVERRIDE; + + virtual IOReturn IOSurfaceLock(CFTypeRef io_surface, + uint32 options, + uint32* seed) OVERRIDE; + virtual IOReturn IOSurfaceUnlock(CFTypeRef io_surface, + uint32 options, + uint32* seed) OVERRIDE; virtual CGLError CGLTexImageIOSurface2D(CGLContextObj ctx, GLenum target, @@ -73,6 +92,7 @@ class IOSurfaceSupportImpl : public IOSurfaceSupport { CFStringRef k_io_surface_width_; CFStringRef k_io_surface_height_; CFStringRef k_io_surface_bytes_per_element_; + CFStringRef k_io_surface_pixel_format_; CFStringRef k_io_surface_is_global_; IOSurfaceCreateProcPtr io_surface_create_; IOSurfaceGetIDProcPtr io_surface_get_id_; @@ -81,6 +101,10 @@ class IOSurfaceSupportImpl : public IOSurfaceSupport { IOSurfaceLookupFromMachPortProcPtr io_surface_lookup_from_mach_port_; IOSurfaceGetWidthPtr io_surface_get_width_; IOSurfaceGetHeightPtr io_surface_get_height_; + IOSurfaceGetBytesPerRowPtr io_surface_get_bytes_per_row_; + IOSurfaceGetBaseAddressPtr io_surface_get_base_address_; + IOSurfaceLockPtr io_surface_lock_; + IOSurfaceUnlockPtr io_surface_unlock_; CGLTexImageIOSurface2DProcPtr cgl_tex_image_io_surface_2d_; CVPixelBufferGetIOSurfaceProcPtr cv_pixel_buffer_get_io_surface_; bool initialized_successfully_; @@ -108,6 +132,10 @@ CFStringRef IOSurfaceSupportImpl::GetKIOSurfaceBytesPerElement() { return k_io_surface_bytes_per_element_; } +CFStringRef IOSurfaceSupportImpl::GetKIOSurfacePixelFormat() { + return k_io_surface_pixel_format_; +} + CFStringRef IOSurfaceSupportImpl::GetKIOSurfaceIsGlobal() { return k_io_surface_is_global_; } @@ -142,6 +170,25 @@ size_t IOSurfaceSupportImpl::IOSurfaceGetHeight(CFTypeRef io_surface) { return io_surface_get_height_(io_surface); } +size_t IOSurfaceSupportImpl::IOSurfaceGetBytesPerRow(CFTypeRef io_surface) { + return io_surface_get_bytes_per_row_(io_surface); +} + +void* IOSurfaceSupportImpl::IOSurfaceGetBaseAddress(CFTypeRef io_surface) { + return io_surface_get_base_address_(io_surface); +} + +IOReturn IOSurfaceSupportImpl::IOSurfaceLock(CFTypeRef io_surface, + uint32 options, + uint32* seed) { + return io_surface_lock_(io_surface, options, seed); +} + +IOReturn IOSurfaceSupportImpl::IOSurfaceUnlock(CFTypeRef io_surface, + uint32 options, + uint32* seed) { + return io_surface_unlock_(io_surface, options, seed); +} CGLError IOSurfaceSupportImpl::CGLTexImageIOSurface2D(CGLContextObj ctx, GLenum target, @@ -175,6 +222,7 @@ IOSurfaceSupportImpl::IOSurfaceSupportImpl() k_io_surface_width_(NULL), k_io_surface_height_(NULL), k_io_surface_bytes_per_element_(NULL), + k_io_surface_pixel_format_(NULL), k_io_surface_is_global_(NULL), io_surface_create_(NULL), io_surface_get_id_(NULL), @@ -183,6 +231,10 @@ IOSurfaceSupportImpl::IOSurfaceSupportImpl() io_surface_lookup_from_mach_port_(NULL), io_surface_get_width_(NULL), io_surface_get_height_(NULL), + io_surface_get_bytes_per_row_(NULL), + io_surface_get_base_address_(NULL), + io_surface_lock_(NULL), + io_surface_unlock_(NULL), cgl_tex_image_io_surface_2d_(NULL), cv_pixel_buffer_get_io_surface_(NULL), initialized_successfully_(false) { @@ -206,6 +258,8 @@ IOSurfaceSupportImpl::IOSurfaceSupportImpl() void* surface_height_ptr = dlsym(iosurface_handle_, "kIOSurfaceHeight"); void* surface_bytes_per_element_ptr = dlsym(iosurface_handle_, "kIOSurfaceBytesPerElement"); + void* surface_pixel_format_ptr = + dlsym(iosurface_handle_, "kIOSurfacePixelFormat"); void* surface_is_global_ptr = dlsym(iosurface_handle_, "kIOSurfaceIsGlobal"); void* surface_create_ptr = dlsym(iosurface_handle_, "IOSurfaceCreate"); @@ -219,6 +273,12 @@ IOSurfaceSupportImpl::IOSurfaceSupportImpl() dlsym(iosurface_handle_, "IOSurfaceGetWidth"); void* io_surface_get_height_ptr = dlsym(iosurface_handle_, "IOSurfaceGetHeight"); + void* io_surface_get_bytes_per_row_ptr = + dlsym(iosurface_handle_, "IOSurfaceGetBytesPerRow"); + void* io_surface_get_base_address_ptr = + dlsym(iosurface_handle_, "IOSurfaceGetBaseAddress"); + void* io_surface_lock_ptr = dlsym(iosurface_handle_, "IOSurfaceLock"); + void* io_surface_unlock_ptr = dlsym(iosurface_handle_, "IOSurfaceUnlock"); void* tex_image_io_surface_2d_ptr = dlsym(opengl_handle_, "CGLTexImageIOSurface2D"); void* cv_pixel_buffer_get_io_surface = @@ -226,6 +286,7 @@ IOSurfaceSupportImpl::IOSurfaceSupportImpl() if (!surface_width_ptr || !surface_height_ptr || !surface_bytes_per_element_ptr || + !surface_pixel_format_ptr || !surface_is_global_ptr || !surface_create_ptr || !surface_get_id_ptr || @@ -234,6 +295,10 @@ IOSurfaceSupportImpl::IOSurfaceSupportImpl() !surface_lookup_from_mach_port_ptr || !io_surface_get_width_ptr || !io_surface_get_height_ptr || + !io_surface_get_bytes_per_row_ptr || + !io_surface_get_base_address_ptr || + !io_surface_lock_ptr || + !io_surface_unlock_ptr || !tex_image_io_surface_2d_ptr || !cv_pixel_buffer_get_io_surface) { CloseLibraryHandles(); @@ -244,6 +309,8 @@ IOSurfaceSupportImpl::IOSurfaceSupportImpl() k_io_surface_height_ = *static_cast<CFStringRef*>(surface_height_ptr); k_io_surface_bytes_per_element_ = *static_cast<CFStringRef*>(surface_bytes_per_element_ptr); + k_io_surface_pixel_format_ = + *static_cast<CFStringRef*>(surface_pixel_format_ptr); k_io_surface_is_global_ = *static_cast<CFStringRef*>(surface_is_global_ptr); io_surface_create_ = reinterpret_cast<IOSurfaceCreateProcPtr>( surface_create_ptr); @@ -263,6 +330,15 @@ IOSurfaceSupportImpl::IOSurfaceSupportImpl() io_surface_get_height_ = reinterpret_cast<IOSurfaceGetHeightPtr>( io_surface_get_height_ptr); + io_surface_get_bytes_per_row_ = + reinterpret_cast<IOSurfaceGetBytesPerRowPtr>( + io_surface_get_bytes_per_row_ptr); + io_surface_get_base_address_ = + reinterpret_cast<IOSurfaceGetBaseAddressPtr>( + io_surface_get_base_address_ptr); + io_surface_lock_ = reinterpret_cast<IOSurfaceLockPtr>(io_surface_lock_ptr); + io_surface_unlock_ = reinterpret_cast<IOSurfaceUnlockPtr>( + io_surface_unlock_ptr); cgl_tex_image_io_surface_2d_ = reinterpret_cast<CGLTexImageIOSurface2DProcPtr>( tex_image_io_surface_2d_ptr); diff --git a/ui/gl/io_surface_support_mac.h b/ui/gl/io_surface_support_mac.h index d8c30e1..d8699c8 100644 --- a/ui/gl/io_surface_support_mac.h +++ b/ui/gl/io_surface_support_mac.h @@ -31,6 +31,7 @@ class GL_EXPORT IOSurfaceSupport { virtual CFStringRef GetKIOSurfaceWidth() = 0; virtual CFStringRef GetKIOSurfaceHeight() = 0; virtual CFStringRef GetKIOSurfaceBytesPerElement() = 0; + virtual CFStringRef GetKIOSurfacePixelFormat() = 0; virtual CFStringRef GetKIOSurfaceIsGlobal() = 0; virtual CFTypeRef IOSurfaceCreate(CFDictionaryRef properties) = 0; @@ -49,6 +50,15 @@ class GL_EXPORT IOSurfaceSupport { virtual size_t IOSurfaceGetWidth(CFTypeRef io_surface) = 0; virtual size_t IOSurfaceGetHeight(CFTypeRef io_surface) = 0; + virtual size_t IOSurfaceGetBytesPerRow(CFTypeRef io_surface) = 0; + virtual void* IOSurfaceGetBaseAddress(CFTypeRef io_surface) = 0; + + virtual IOReturn IOSurfaceLock(CFTypeRef io_surface, + uint32 options, + uint32* seed) = 0; + virtual IOReturn IOSurfaceUnlock(CFTypeRef io_surface, + uint32 options, + uint32* seed) = 0; virtual CGLError CGLTexImageIOSurface2D(CGLContextObj ctx, GLenum target, |