ion_buffer.cpp revision cd52dd9f1b301854b4e1734e3741d9cef8f784b1
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                     uint32_t usage)
22    : IonBuffer(width, height, format, usage, usage) {}
23
24IonBuffer::IonBuffer(uint32_t width, uint32_t height, uint32_t format,
25                     uint64_t producer_usage, uint64_t consumer_usage)
26    : IonBuffer() {
27  Alloc(width, height, format, producer_usage, consumer_usage);
28}
29
30IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
31                     uint32_t stride, uint32_t format, uint32_t usage)
32    : IonBuffer(handle, width, height, 1, stride, 0, format, usage) {}
33
34IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
35                     uint32_t layer_count, uint32_t stride,
36                     uint32_t layer_stride, uint32_t format, uint32_t usage)
37    : IonBuffer(handle, width, height, layer_count, stride, layer_stride,
38                format, usage, usage) {}
39
40IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
41                     uint32_t layer_count, uint32_t stride,
42                     uint32_t layer_stride, uint32_t format,
43                     uint64_t producer_usage, uint64_t consumer_usage)
44    : buffer_(nullptr) {
45  ALOGD_IF(TRACE,
46           "IonBuffer::IonBuffer: handle=%p width=%u height=%u layer_count=%u "
47           "stride=%u layer stride=%u format=%u producer_usage=%" PRIx64
48           " consumer_usage=%" PRIx64,
49           handle, width, height, layer_count, stride, layer_stride, format,
50           producer_usage, consumer_usage);
51  if (handle != 0) {
52    Import(handle, width, height, stride, format, producer_usage,
53           consumer_usage);
54  }
55}
56
57IonBuffer::~IonBuffer() {
58  ALOGD_IF(TRACE,
59           "IonBuffer::~IonBuffer: handle=%p width=%u height=%u stride=%u "
60           "format=%u usage=%x",
61           handle(), width(), height(), stride(), format(), usage());
62  FreeHandle();
63}
64
65IonBuffer::IonBuffer(IonBuffer&& other) : IonBuffer() {
66  *this = std::move(other);
67}
68
69IonBuffer& IonBuffer::operator=(IonBuffer&& other) {
70  ALOGD_IF(TRACE, "IonBuffer::operator=: handle_=%p other.handle_=%p", handle(),
71           other.handle());
72
73  if (this != &other) {
74    buffer_ = other.buffer_;
75    other.FreeHandle();
76  }
77  return *this;
78}
79
80void IonBuffer::FreeHandle() {
81  if (buffer_.get()) {
82    // GraphicBuffer unregisters and cleans up the handle if needed
83    buffer_ = nullptr;
84    producer_usage_ = 0;
85    consumer_usage_ = 0;
86  }
87}
88
89int IonBuffer::Alloc(uint32_t width, uint32_t height, uint32_t format,
90                     uint32_t usage) {
91  return Alloc(width, height, format, usage, usage);
92}
93
94int IonBuffer::Alloc(uint32_t width, uint32_t height, uint32_t format,
95                     uint64_t producer_usage, uint64_t consumer_usage) {
96  ALOGD_IF(
97      TRACE,
98      "IonBuffer::Alloc: width=%u height=%u format=%u producer_usage=%" PRIx64
99      " consumer_usage=%" PRIx64,
100      width, height, format, producer_usage, consumer_usage);
101
102  sp<GraphicBuffer> buffer =
103      new GraphicBuffer(width, height, format, kDefaultGraphicBufferLayerCount,
104                        producer_usage, consumer_usage);
105  if (buffer->initCheck() != OK) {
106    ALOGE("IonBuffer::Aloc: Failed to allocate buffer");
107    return -EINVAL;
108  } else {
109    buffer_ = buffer;
110    producer_usage_ = producer_usage;
111    consumer_usage_ = consumer_usage;
112    return 0;
113  }
114}
115
116void IonBuffer::Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
117                      uint32_t stride, uint32_t format, uint32_t usage) {
118  Reset(handle, width, height, stride, format, usage, usage);
119}
120
121void IonBuffer::Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
122                      uint32_t stride, uint32_t format, uint64_t producer_usage,
123                      uint64_t consumer_usage) {
124  ALOGD_IF(TRACE,
125           "IonBuffer::Reset: handle=%p width=%u height=%u stride=%u format=%u "
126           "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64,
127           handle, width, height, stride, format, producer_usage,
128           consumer_usage);
129  Import(handle, width, height, stride, format, producer_usage, consumer_usage);
130}
131
132int IonBuffer::Import(buffer_handle_t handle, uint32_t width, uint32_t height,
133                      uint32_t stride, uint32_t format, uint32_t usage) {
134  return Import(handle, width, height, stride, format, usage, usage);
135}
136
137int IonBuffer::Import(buffer_handle_t handle, uint32_t width, uint32_t height,
138                      uint32_t stride, uint32_t format, uint64_t producer_usage,
139                      uint64_t consumer_usage) {
140  ATRACE_NAME("IonBuffer::Import1");
141  ALOGD_IF(
142      TRACE,
143      "IonBuffer::Import: handle=%p width=%u height=%u stride=%u format=%u "
144      "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64,
145      handle, width, height, stride, format, producer_usage, consumer_usage);
146  FreeHandle();
147  sp<GraphicBuffer> buffer = new GraphicBuffer(
148      handle, GraphicBuffer::TAKE_UNREGISTERED_HANDLE, width, height, format,
149      kDefaultGraphicBufferLayerCount, producer_usage, consumer_usage, stride);
150  if (buffer->initCheck() != OK) {
151    ALOGE("IonBuffer::Import: Failed to import buffer");
152    return -EINVAL;
153  } else {
154    buffer_ = buffer;
155    producer_usage_ = producer_usage;
156    consumer_usage_ = consumer_usage;
157    return 0;
158  }
159}
160
161int IonBuffer::Import(const int* fd_array, int fd_count, const int* int_array,
162                      int int_count, uint32_t width, uint32_t height,
163                      uint32_t stride, uint32_t format, uint32_t usage) {
164  return Import(fd_array, fd_count, int_array, int_count, width, height, stride,
165                format, usage, usage);
166}
167
168int IonBuffer::Import(const int* fd_array, int fd_count, const int* int_array,
169                      int int_count, uint32_t width, uint32_t height,
170                      uint32_t stride, uint32_t format, uint64_t producer_usage,
171                      uint64_t consumer_usage) {
172  ATRACE_NAME("IonBuffer::Import2");
173  ALOGD_IF(TRACE,
174           "IonBuffer::Import: fd_count=%d int_count=%d width=%u height=%u "
175           "stride=%u format=%u producer_usage=%" PRIx64
176           " consumer_usage=%" PRIx64,
177           fd_count, int_count, width, height, stride, format, producer_usage,
178           consumer_usage);
179
180  if (fd_count < 0 || int_count < 0) {
181    ALOGE("IonBuffer::Import: invalid arguments.");
182    return -EINVAL;
183  }
184
185  native_handle_t* handle = native_handle_create(fd_count, int_count);
186  if (!handle) {
187    ALOGE("IonBuffer::Import: failed to create new native handle.");
188    return -ENOMEM;
189  }
190
191  // Copy fd_array into the first part of handle->data and int_array right
192  // after it.
193  memcpy(handle->data, fd_array, sizeof(int) * fd_count);
194  memcpy(handle->data + fd_count, int_array, sizeof(int) * int_count);
195
196  const int ret = Import(handle, width, height, stride, format, producer_usage,
197                         consumer_usage);
198  if (ret < 0) {
199    ALOGE("IonBuffer::Import: failed to import raw native handle: %s",
200          strerror(-ret));
201    native_handle_close(handle);
202    native_handle_delete(handle);
203  }
204
205  return ret;
206}
207
208int IonBuffer::Duplicate(const IonBuffer* other) {
209  if (!other->handle())
210    return -EINVAL;
211
212  const int fd_count = other->handle()->numFds;
213  const int int_count = other->handle()->numInts;
214
215  if (fd_count < 0 || int_count < 0)
216    return -EINVAL;
217
218  native_handle_t* handle = native_handle_create(fd_count, int_count);
219  if (!handle) {
220    ALOGE("IonBuffer::Duplicate: Failed to create new native handle.");
221    return -ENOMEM;
222  }
223
224  // Duplicate the file descriptors from the other native handle.
225  for (int i = 0; i < fd_count; i++)
226    handle->data[i] = dup(other->handle()->data[i]);
227
228  // Copy the ints after the file descriptors.
229  memcpy(handle->data + fd_count, other->handle()->data + fd_count,
230         sizeof(int) * int_count);
231
232  const int ret =
233      Import(handle, other->width(), other->height(), other->stride(),
234             other->format(), other->producer_usage(), other->consumer_usage());
235  if (ret < 0) {
236    ALOGE("IonBuffer::Duplicate: Failed to import duplicate native handle: %s",
237          strerror(-ret));
238    native_handle_close(handle);
239    native_handle_delete(handle);
240  }
241
242  return ret;
243}
244
245int IonBuffer::Lock(uint32_t usage, int x, int y, int width, int height,
246                    void** address) {
247  ATRACE_NAME("IonBuffer::Lock");
248  ALOGD_IF(TRACE,
249           "IonBuffer::Lock: handle=%p usage=%d x=%d y=%d width=%d height=%d "
250           "address=%p",
251           handle(), usage, x, y, width, height, address);
252
253  status_t err =
254      buffer_->lock(usage, Rect(x, y, x + width, y + height), address);
255  if (err != NO_ERROR)
256    return -EINVAL;
257  else
258    return 0;
259}
260
261int IonBuffer::LockYUV(uint32_t usage, int x, int y, int width, int height,
262                       struct android_ycbcr* yuv) {
263  ATRACE_NAME("IonBuffer::LockYUV");
264  ALOGD_IF(TRACE,
265           "IonBuffer::Lock: handle=%p usage=%d x=%d y=%d width=%d height=%d",
266           handle(), usage, x, y, width, height);
267
268  status_t err =
269      buffer_->lockYCbCr(usage, Rect(x, y, x + width, y + height), yuv);
270  if (err != NO_ERROR)
271    return -EINVAL;
272  else
273    return 0;
274}
275
276int IonBuffer::Unlock() {
277  ATRACE_NAME("IonBuffer::Unlock");
278  ALOGD_IF(TRACE, "IonBuffer::Unlock: handle=%p", handle());
279
280  status_t err = buffer_->unlock();
281  if (err != NO_ERROR)
282    return -EINVAL;
283  else
284    return 0;
285}
286}  // namespace dvr
287}  // namespace android
288