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