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