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