blob: df9ae81a38f78aa5cc62ec66a22c06b624825137 [file] [log] [blame]
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08001#include <private/dvr/ion_buffer.h>
2
Alex Vakulenko4fe60582017-02-02 11:35:59 -08003#include <log/log.h>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08004#define ATRACE_TAG ATRACE_TAG_GRAPHICS
5#include <utils/Trace.h>
6
7#include <mutex>
8
Corey Tabakacd52dd92017-04-07 18:03:57 -07009namespace {
10
11constexpr uint32_t kDefaultGraphicBufferLayerCount = 1;
12
13} // anonymous namespace
14
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080015namespace android {
16namespace dvr {
17
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080018IonBuffer::IonBuffer() : IonBuffer(nullptr, 0, 0, 0, 0, 0, 0, 0) {}
19
Corey Tabakacd52dd92017-04-07 18:03:57 -070020IonBuffer::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)
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080026 : IonBuffer() {
Corey Tabakacd52dd92017-04-07 18:03:57 -070027 Alloc(width, height, format, producer_usage, consumer_usage);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080028}
29
Corey Tabakacd52dd92017-04-07 18:03:57 -070030IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
31 uint32_t stride, uint32_t format, uint32_t usage)
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080032 : IonBuffer(handle, width, height, 1, stride, 0, format, usage) {}
33
Corey Tabakacd52dd92017-04-07 18:03:57 -070034IonBuffer::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) {}
Mark Urbanus8a71b132017-03-16 11:06:51 -070039
Corey Tabakacd52dd92017-04-07 18:03:57 -070040IonBuffer::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)
Mark Urbanus8a71b132017-03-16 11:06:51 -070044 : buffer_(nullptr) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080045 ALOGD_IF(TRACE,
Corey Tabakacd52dd92017-04-07 18:03:57 -070046 "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);
Mark Urbanus8a71b132017-03-16 11:06:51 -070051 if (handle != 0) {
Corey Tabakacd52dd92017-04-07 18:03:57 -070052 Import(handle, width, height, stride, format, producer_usage,
53 consumer_usage);
Mark Urbanus8a71b132017-03-16 11:06:51 -070054 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080055}
56
57IonBuffer::~IonBuffer() {
58 ALOGD_IF(TRACE,
Corey Tabakacd52dd92017-04-07 18:03:57 -070059 "IonBuffer::~IonBuffer: handle=%p width=%u height=%u stride=%u "
60 "format=%u usage=%x",
61 handle(), width(), height(), stride(), format(), usage());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080062 FreeHandle();
63}
64
65IonBuffer::IonBuffer(IonBuffer&& other) : IonBuffer() {
66 *this = std::move(other);
67}
68
69IonBuffer& IonBuffer::operator=(IonBuffer&& other) {
Mark Urbanus8a71b132017-03-16 11:06:51 -070070 ALOGD_IF(TRACE, "IonBuffer::operator=: handle_=%p other.handle_=%p", handle(),
71 other.handle());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080072
73 if (this != &other) {
Mark Urbanus8a71b132017-03-16 11:06:51 -070074 buffer_ = other.buffer_;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080075 other.FreeHandle();
76 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080077 return *this;
78}
79
80void IonBuffer::FreeHandle() {
Mark Urbanus8a71b132017-03-16 11:06:51 -070081 if (buffer_.get()) {
82 // GraphicBuffer unregisters and cleans up the handle if needed
83 buffer_ = nullptr;
Corey Tabakacd52dd92017-04-07 18:03:57 -070084 producer_usage_ = 0;
85 consumer_usage_ = 0;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080086 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080087}
88
Corey Tabakacd52dd92017-04-07 18:03:57 -070089int IonBuffer::Alloc(uint32_t width, uint32_t height, uint32_t format,
90 uint32_t usage) {
91 return Alloc(width, height, format, usage, usage);
92}
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080093
Corey Tabakacd52dd92017-04-07 18:03:57 -070094int 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) {
Chia-I Wub42f1712017-03-21 13:15:39 -0700106 ALOGE("IonBuffer::Aloc: Failed to allocate buffer");
Corey Tabakacd52dd92017-04-07 18:03:57 -0700107 return -EINVAL;
108 } else {
109 buffer_ = buffer;
110 producer_usage_ = producer_usage;
111 consumer_usage_ = consumer_usage;
112 return 0;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800113 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800114}
115
Corey Tabakacd52dd92017-04-07 18:03:57 -0700116void 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) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800124 ALOGD_IF(TRACE,
Corey Tabakacd52dd92017-04-07 18:03:57 -0700125 "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);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800130}
131
Corey Tabakacd52dd92017-04-07 18:03:57 -0700132int 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) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800140 ATRACE_NAME("IonBuffer::Import1");
141 ALOGD_IF(
142 TRACE,
Corey Tabakacd52dd92017-04-07 18:03:57 -0700143 "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);
Mark Urbanus8a71b132017-03-16 11:06:51 -0700146 FreeHandle();
Corey Tabakacd52dd92017-04-07 18:03:57 -0700147 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) {
Chia-I Wub42f1712017-03-21 13:15:39 -0700151 ALOGE("IonBuffer::Import: Failed to import buffer");
Mark Urbanus8a71b132017-03-16 11:06:51 -0700152 return -EINVAL;
Corey Tabakacd52dd92017-04-07 18:03:57 -0700153 } else {
154 buffer_ = buffer;
155 producer_usage_ = producer_usage;
156 consumer_usage_ = consumer_usage;
157 return 0;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800158 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800159}
160
161int IonBuffer::Import(const int* fd_array, int fd_count, const int* int_array,
Corey Tabakacd52dd92017-04-07 18:03:57 -0700162 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) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800172 ATRACE_NAME("IonBuffer::Import2");
173 ALOGD_IF(TRACE,
Corey Tabakacd52dd92017-04-07 18:03:57 -0700174 "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);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800179
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
Corey Tabakacd52dd92017-04-07 18:03:57 -0700196 const int ret = Import(handle, width, height, stride, format, producer_usage,
197 consumer_usage);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800198 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
Corey Tabakacd52dd92017-04-07 18:03:57 -0700232 const int ret =
233 Import(handle, other->width(), other->height(), other->stride(),
234 other->format(), other->producer_usage(), other->consumer_usage());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800235 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
Corey Tabakacd52dd92017-04-07 18:03:57 -0700245int IonBuffer::Lock(uint32_t usage, int x, int y, int width, int height,
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800246 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",
Mark Urbanus8a71b132017-03-16 11:06:51 -0700251 handle(), usage, x, y, width, height, address);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800252
Corey Tabakacd52dd92017-04-07 18:03:57 -0700253 status_t err =
254 buffer_->lock(usage, Rect(x, y, x + width, y + height), address);
Mark Urbanus8a71b132017-03-16 11:06:51 -0700255 if (err != NO_ERROR)
256 return -EINVAL;
257 else
258 return 0;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800259}
260
Corey Tabakacd52dd92017-04-07 18:03:57 -0700261int IonBuffer::LockYUV(uint32_t usage, int x, int y, int width, int height,
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800262 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",
Mark Urbanus8a71b132017-03-16 11:06:51 -0700266 handle(), usage, x, y, width, height);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800267
Corey Tabakacd52dd92017-04-07 18:03:57 -0700268 status_t err =
269 buffer_->lockYCbCr(usage, Rect(x, y, x + width, y + height), yuv);
Mark Urbanus8a71b132017-03-16 11:06:51 -0700270 if (err != NO_ERROR)
271 return -EINVAL;
272 else
273 return 0;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800274}
275
276int IonBuffer::Unlock() {
277 ATRACE_NAME("IonBuffer::Unlock");
Mark Urbanus8a71b132017-03-16 11:06:51 -0700278 ALOGD_IF(TRACE, "IonBuffer::Unlock: handle=%p", handle());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800279
Mark Urbanus8a71b132017-03-16 11:06:51 -0700280 status_t err = buffer_->unlock();
281 if (err != NO_ERROR)
282 return -EINVAL;
283 else
284 return 0;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800285}
Corey Tabakacd52dd92017-04-07 18:03:57 -0700286} // namespace dvr
287} // namespace android