1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h"
6
7#include "base/atomic_sequence_num.h"
8#include "base/bind.h"
9#include "base/logging.h"
10#include "content/common/gpu/client/gpu_memory_buffer_factory_host.h"
11#include "ui/gl/gl_bindings.h"
12
13namespace content {
14namespace {
15
16base::StaticAtomicSequenceNumber g_next_buffer_id;
17
18void Noop() {
19}
20
21void GpuMemoryBufferCreated(
22    const gfx::Size& size,
23    unsigned internalformat,
24    const GpuMemoryBufferImpl::CreationCallback& callback,
25    const gfx::GpuMemoryBufferHandle& handle) {
26  DCHECK_EQ(gfx::IO_SURFACE_BUFFER, handle.type);
27
28  callback.Run(GpuMemoryBufferImplIOSurface::CreateFromHandle(
29      handle, size, internalformat, base::Bind(&Noop)));
30}
31
32void GpuMemoryBufferCreatedForChildProcess(
33    const GpuMemoryBufferImpl::AllocationCallback& callback,
34    const gfx::GpuMemoryBufferHandle& handle) {
35  DCHECK_EQ(gfx::IO_SURFACE_BUFFER, handle.type);
36
37  callback.Run(handle);
38}
39
40}  // namespace
41
42GpuMemoryBufferImplIOSurface::GpuMemoryBufferImplIOSurface(
43    const gfx::Size& size,
44    unsigned internalformat,
45    const DestructionCallback& callback,
46    IOSurfaceRef io_surface)
47    : GpuMemoryBufferImpl(size, internalformat, callback),
48      io_surface_(io_surface) {
49}
50
51GpuMemoryBufferImplIOSurface::~GpuMemoryBufferImplIOSurface() {
52}
53
54// static
55void GpuMemoryBufferImplIOSurface::Create(const gfx::Size& size,
56                                          unsigned internalformat,
57                                          unsigned usage,
58                                          int client_id,
59                                          const CreationCallback& callback) {
60  gfx::GpuMemoryBufferHandle handle;
61  handle.type = gfx::IO_SURFACE_BUFFER;
62  handle.global_id.primary_id = g_next_buffer_id.GetNext();
63  handle.global_id.secondary_id = client_id;
64  GpuMemoryBufferFactoryHost::GetInstance()->CreateGpuMemoryBuffer(
65      handle,
66      size,
67      internalformat,
68      usage,
69      base::Bind(&GpuMemoryBufferCreated, size, internalformat, callback));
70}
71
72// static
73void GpuMemoryBufferImplIOSurface::AllocateForChildProcess(
74    const gfx::Size& size,
75    unsigned internalformat,
76    unsigned usage,
77    int child_client_id,
78    const AllocationCallback& callback) {
79  gfx::GpuMemoryBufferHandle handle;
80  handle.type = gfx::IO_SURFACE_BUFFER;
81  handle.global_id.primary_id = g_next_buffer_id.GetNext();
82  handle.global_id.secondary_id = child_client_id;
83  GpuMemoryBufferFactoryHost::GetInstance()->CreateGpuMemoryBuffer(
84      handle,
85      size,
86      internalformat,
87      usage,
88      base::Bind(&GpuMemoryBufferCreatedForChildProcess, callback));
89}
90
91// static
92scoped_ptr<GpuMemoryBufferImpl> GpuMemoryBufferImplIOSurface::CreateFromHandle(
93    const gfx::GpuMemoryBufferHandle& handle,
94    const gfx::Size& size,
95    unsigned internalformat,
96    const DestructionCallback& callback) {
97  DCHECK(IsFormatSupported(internalformat));
98
99  base::ScopedCFTypeRef<IOSurfaceRef> io_surface(
100      IOSurfaceLookup(handle.io_surface_id));
101  if (!io_surface)
102    return scoped_ptr<GpuMemoryBufferImpl>();
103
104  return make_scoped_ptr<GpuMemoryBufferImpl>(new GpuMemoryBufferImplIOSurface(
105      size, internalformat, callback, io_surface.get()));
106}
107
108// static
109bool GpuMemoryBufferImplIOSurface::IsFormatSupported(unsigned internalformat) {
110  switch (internalformat) {
111    case GL_BGRA8_EXT:
112      return true;
113    default:
114      return false;
115  }
116}
117
118// static
119bool GpuMemoryBufferImplIOSurface::IsUsageSupported(unsigned usage) {
120  switch (usage) {
121    case GL_IMAGE_MAP_CHROMIUM:
122      return true;
123    default:
124      return false;
125  }
126}
127
128// static
129bool GpuMemoryBufferImplIOSurface::IsConfigurationSupported(
130    unsigned internalformat,
131    unsigned usage) {
132  return IsFormatSupported(internalformat) && IsUsageSupported(usage);
133}
134
135// static
136uint32 GpuMemoryBufferImplIOSurface::PixelFormat(unsigned internalformat) {
137  switch (internalformat) {
138    case GL_BGRA8_EXT:
139      return 'BGRA';
140    default:
141      NOTREACHED();
142      return 0;
143  }
144}
145
146void* GpuMemoryBufferImplIOSurface::Map() {
147  DCHECK(!mapped_);
148  IOSurfaceLock(io_surface_, 0, NULL);
149  mapped_ = true;
150  return IOSurfaceGetBaseAddress(io_surface_);
151}
152
153void GpuMemoryBufferImplIOSurface::Unmap() {
154  DCHECK(mapped_);
155  IOSurfaceUnlock(io_surface_, 0, NULL);
156  mapped_ = false;
157}
158
159uint32 GpuMemoryBufferImplIOSurface::GetStride() const {
160  return IOSurfaceGetBytesPerRow(io_surface_);
161}
162
163gfx::GpuMemoryBufferHandle GpuMemoryBufferImplIOSurface::GetHandle() const {
164  gfx::GpuMemoryBufferHandle handle;
165  handle.type = gfx::IO_SURFACE_BUFFER;
166  handle.io_surface_id = IOSurfaceGetID(io_surface_);
167  return handle;
168}
169
170}  // namespace content
171