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) noexcept : IonBuffer() {
53 *this = std::move(other);
54 }
55
operator =(IonBuffer && other)56 IonBuffer& IonBuffer::operator=(IonBuffer&& other) noexcept {
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 != OK)
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 != OK)
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 != OK)
235 return -EINVAL;
236 else
237 return 0;
238 }
239 } // namespace dvr
240 } // namespace android
241