summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorreveman@chromium.org <reveman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-05 01:02:12 +0000
committerreveman@chromium.org <reveman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-05 01:02:12 +0000
commit8810516771cd7414f6d05f851666061b6b8bca9a (patch)
tree545ddedbc70d6f32ccd035417e6def969528e037
parent7b69f87961fa5e8a948df0072819424d0b041d3d (diff)
downloadchromium_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
-rw-r--r--content/browser/gpu/browser_gpu_channel_host_factory.cc13
-rw-r--r--content/browser/renderer_host/render_message_filter.cc101
-rw-r--r--content/browser/renderer_host/render_message_filter.h9
-rw-r--r--content/common/child_process_host_impl.cc10
-rw-r--r--content/common/child_process_host_impl.h4
-rw-r--r--content/common/child_process_messages.h9
-rw-r--r--content/common/gpu/client/gpu_channel_host.cc7
-rw-r--r--content/common/gpu/client/gpu_memory_buffer_impl.cc47
-rw-r--r--content/common/gpu/client/gpu_memory_buffer_impl.h24
-rw-r--r--content/common/gpu/client/gpu_memory_buffer_impl_android.cc29
-rw-r--r--content/common/gpu/client/gpu_memory_buffer_impl_io_surface.cc79
-rw-r--r--content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h42
-rw-r--r--content/common/gpu/client/gpu_memory_buffer_impl_linux.cc29
-rw-r--r--content/common/gpu/client/gpu_memory_buffer_impl_mac.cc38
-rw-r--r--content/common/gpu/client/gpu_memory_buffer_impl_ozone.cc29
-rw-r--r--content/common/gpu/client/gpu_memory_buffer_impl_shm.cc56
-rw-r--r--content/common/gpu/client/gpu_memory_buffer_impl_shm.h36
-rw-r--r--content/common/gpu/client/gpu_memory_buffer_impl_win.cc29
-rw-r--r--content/common/sandbox_mac.mm10
-rw-r--r--content/content_common.gypi11
-rw-r--r--content/renderer/render_thread_impl.cc33
-rw-r--r--content/renderer/render_thread_impl.h6
-rw-r--r--ui/gfx/gpu_memory_buffer.h10
-rw-r--r--ui/gl/gl.gyp2
-rw-r--r--ui/gl/gl_image_io_surface.cc79
-rw-r--r--ui/gl/gl_image_io_surface.h42
-rw-r--r--ui/gl/gl_image_mac.cc8
-rw-r--r--ui/gl/io_surface_support_mac.cc76
-rw-r--r--ui/gl/io_surface_support_mac.h10
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,