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