ion_buffer.cpp revision 8a71b13127f737a46c55ba94d31ba0262e7cbf8a
1#include <private/dvr/ion_buffer.h>
2#include <ui/GraphicBufferMapper.h>
3
4#include <log/log.h>
5#define ATRACE_TAG ATRACE_TAG_GRAPHICS
6#include <utils/Trace.h>
7
8#include <mutex>
9
10namespace android {
11namespace dvr {
12
13IonBuffer::IonBuffer() : IonBuffer(nullptr, 0, 0, 0, 0, 0, 0, 0) {}
14
15IonBuffer::IonBuffer(int width, int height, int format, int usage)
16    : IonBuffer() {
17  Alloc(width, height, format, usage);
18}
19
20IonBuffer::IonBuffer(buffer_handle_t handle, int width, int height, int stride,
21                     int format, int usage)
22    : IonBuffer(handle, width, height, 1, stride, 0, format, usage) {}
23
24
25IonBuffer::IonBuffer(buffer_handle_t handle, int width, int height,
26                     int layer_count, int stride, int layer_stride, int format,
27                     int usage)
28    : buffer_(nullptr) {
29  ALOGD_IF(TRACE,
30         "IonBuffer::IonBuffer: handle=%p width=%d height=%d layer_count=%d "
31         "stride=%d layer stride=%d format=%d usage=%d",
32         handle, width, height, layer_count, stride, layer_stride,
33         format, usage);
34  if (handle != 0) {
35    Import(handle, width, height, stride, format, usage);
36  }
37}
38
39IonBuffer::~IonBuffer() {
40  ALOGD_IF(TRACE,
41           "IonBuffer::~IonBuffer: handle=%p width=%d height=%d stride=%d "
42           "format=%d usage=%d",
43           handle() , width(), height(), stride(), format(), usage());
44  FreeHandle();
45}
46
47IonBuffer::IonBuffer(IonBuffer&& other) : IonBuffer() {
48  *this = std::move(other);
49}
50
51IonBuffer& IonBuffer::operator=(IonBuffer&& other) {
52  ALOGD_IF(TRACE, "IonBuffer::operator=: handle_=%p other.handle_=%p", handle(),
53           other.handle());
54
55  if (this != &other) {
56    buffer_ = other.buffer_;
57    other.FreeHandle();
58  }
59  return *this;
60}
61
62void IonBuffer::FreeHandle() {
63  if (buffer_.get()) {
64    // GraphicBuffer unregisters and cleans up the handle if needed
65    buffer_ = nullptr;
66  }
67}
68
69int IonBuffer::Alloc(int width, int height, int format, int usage) {
70  ALOGD_IF(TRACE, "IonBuffer::Alloc: width=%d height=%d format=%d usage=%d",
71           width, height, format, usage);
72
73  GraphicBufferMapper& mapper = GraphicBufferMapper::get();
74  buffer_ = new GraphicBuffer(width, height, format, usage);
75  if (mapper.registerBuffer(buffer_.get()) != OK) {
76    ALOGE("IonBuffer::Aloc: Failed to register buffer");
77  }
78  return 0;
79}
80
81void IonBuffer::Reset(buffer_handle_t handle, int width, int height, int stride,
82                      int format, int usage) {
83  ALOGD_IF(TRACE,
84           "IonBuffer::Reset: handle=%p width=%d height=%d stride=%d format=%d "
85           "usage=%d",
86           handle, width, height, stride, format, usage);
87  Import(handle, width, height, stride, format, usage);
88}
89
90int IonBuffer::Import(buffer_handle_t handle, int width, int height, int stride,
91                      int format, int usage) {
92  ATRACE_NAME("IonBuffer::Import1");
93  ALOGD_IF(
94      TRACE,
95      "IonBuffer::Import: handle=%p width=%d height=%d stride=%d format=%d "
96      "usage=%d",
97      handle, width, height, stride, format, usage);
98  FreeHandle();
99  GraphicBufferMapper& mapper = GraphicBufferMapper::get();
100  buffer_ = new GraphicBuffer(width, height, format, 1, usage,
101                              stride, (native_handle_t*)handle, true);
102  if (mapper.registerBuffer(buffer_.get()) != OK) {
103    ALOGE("IonBuffer::Import: Failed to register cloned buffer");
104    return -EINVAL;
105  }
106  return 0;
107}
108
109int IonBuffer::Import(const int* fd_array, int fd_count, const int* int_array,
110                      int int_count, int width, int height, int stride,
111                      int format, int usage) {
112  ATRACE_NAME("IonBuffer::Import2");
113  ALOGD_IF(TRACE,
114           "IonBuffer::Import: fd_count=%d int_count=%d width=%d height=%d "
115           "stride=%d format=%d usage=%d",
116           fd_count, int_count, width, height, stride, format, usage);
117
118  if (fd_count < 0 || int_count < 0) {
119    ALOGE("IonBuffer::Import: invalid arguments.");
120    return -EINVAL;
121  }
122
123  native_handle_t* handle = native_handle_create(fd_count, int_count);
124  if (!handle) {
125    ALOGE("IonBuffer::Import: failed to create new native handle.");
126    return -ENOMEM;
127  }
128
129  // Copy fd_array into the first part of handle->data and int_array right
130  // after it.
131  memcpy(handle->data, fd_array, sizeof(int) * fd_count);
132  memcpy(handle->data + fd_count, int_array, sizeof(int) * int_count);
133
134  int ret = Import(handle, width, height, stride, format, usage);
135  if (ret < 0) {
136    ALOGE("IonBuffer::Import: failed to import raw native handle: %s",
137          strerror(-ret));
138    native_handle_close(handle);
139    native_handle_delete(handle);
140  }
141
142  return ret;
143}
144
145int IonBuffer::Duplicate(const IonBuffer* other) {
146  if (!other->handle())
147    return -EINVAL;
148
149  const int fd_count = other->handle()->numFds;
150  const int int_count = other->handle()->numInts;
151
152  if (fd_count < 0 || int_count < 0)
153    return -EINVAL;
154
155  native_handle_t* handle = native_handle_create(fd_count, int_count);
156  if (!handle) {
157    ALOGE("IonBuffer::Duplicate: Failed to create new native handle.");
158    return -ENOMEM;
159  }
160
161  // Duplicate the file descriptors from the other native handle.
162  for (int i = 0; i < fd_count; i++)
163    handle->data[i] = dup(other->handle()->data[i]);
164
165  // Copy the ints after the file descriptors.
166  memcpy(handle->data + fd_count, other->handle()->data + fd_count,
167         sizeof(int) * int_count);
168
169  const int ret = Import(handle, other->width(), other->height(),
170                         other->stride(), other->format(), other->usage());
171  if (ret < 0) {
172    ALOGE("IonBuffer::Duplicate: Failed to import duplicate native handle: %s",
173          strerror(-ret));
174    native_handle_close(handle);
175    native_handle_delete(handle);
176  }
177
178  return ret;
179}
180
181int IonBuffer::Lock(int usage, int x, int y, int width, int height,
182                    void** address) {
183  ATRACE_NAME("IonBuffer::Lock");
184  ALOGD_IF(TRACE,
185           "IonBuffer::Lock: handle=%p usage=%d x=%d y=%d width=%d height=%d "
186           "address=%p",
187           handle(), usage, x, y, width, height, address);
188
189  status_t err = buffer_->lock(usage, Rect(x, y, x + width, y + height),
190                               address);
191  if (err != NO_ERROR)
192    return -EINVAL;
193  else
194    return 0;
195}
196
197int IonBuffer::LockYUV(int usage, int x, int y, int width, int height,
198                       struct android_ycbcr* yuv) {
199  ATRACE_NAME("IonBuffer::LockYUV");
200  ALOGD_IF(TRACE,
201           "IonBuffer::Lock: handle=%p usage=%d x=%d y=%d width=%d height=%d",
202           handle(), usage, x, y, width, height);
203
204  status_t err = buffer_->lockYCbCr(usage, Rect(x, y, x + width, y + height),
205                                    yuv);
206  if (err != NO_ERROR)
207    return -EINVAL;
208  else
209    return 0;
210}
211
212int IonBuffer::Unlock() {
213  ATRACE_NAME("IonBuffer::Unlock");
214  ALOGD_IF(TRACE, "IonBuffer::Unlock: handle=%p", handle());
215
216  status_t err = buffer_->unlock();
217  if (err != NO_ERROR)
218    return -EINVAL;
219  else
220    return 0;
221}
222} // namespace dvr
223} // namespace android
224