blob: 0a6996edc110024c0987dd831114d3ee3072983f [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
Chris Forbes73feb062017-04-19 17:16:48 -07005#include <grallocusage/GrallocUsageConversion.h>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08006#include <utils/Trace.h>
7
8#include <mutex>
9
Corey Tabakacd52dd92017-04-07 18:03:57 -070010namespace {
11
12constexpr uint32_t kDefaultGraphicBufferLayerCount = 1;
13
14} // anonymous namespace
15
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080016namespace android {
17namespace dvr {
18
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080019IonBuffer::IonBuffer() : IonBuffer(nullptr, 0, 0, 0, 0, 0, 0, 0) {}
20
Corey Tabakacd52dd92017-04-07 18:03:57 -070021IonBuffer::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)
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080027 : IonBuffer() {
Corey Tabakacd52dd92017-04-07 18:03:57 -070028 Alloc(width, height, format, producer_usage, consumer_usage);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080029}
30
Corey Tabakacd52dd92017-04-07 18:03:57 -070031IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
32 uint32_t stride, uint32_t format, uint32_t usage)
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080033 : IonBuffer(handle, width, height, 1, stride, 0, format, usage) {}
34
Corey Tabakacd52dd92017-04-07 18:03:57 -070035IonBuffer::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) {}
Mark Urbanus8a71b132017-03-16 11:06:51 -070040
Corey Tabakacd52dd92017-04-07 18:03:57 -070041IonBuffer::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)
Mark Urbanus8a71b132017-03-16 11:06:51 -070045 : buffer_(nullptr) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080046 ALOGD_IF(TRACE,
Corey Tabakacd52dd92017-04-07 18:03:57 -070047 "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);
Mark Urbanus8a71b132017-03-16 11:06:51 -070052 if (handle != 0) {
Corey Tabakacd52dd92017-04-07 18:03:57 -070053 Import(handle, width, height, stride, format, producer_usage,
54 consumer_usage);
Mark Urbanus8a71b132017-03-16 11:06:51 -070055 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080056}
57
58IonBuffer::~IonBuffer() {
59 ALOGD_IF(TRACE,
Corey Tabakacd52dd92017-04-07 18:03:57 -070060 "IonBuffer::~IonBuffer: handle=%p width=%u height=%u stride=%u "
61 "format=%u usage=%x",
62 handle(), width(), height(), stride(), format(), usage());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080063 FreeHandle();
64}
65
66IonBuffer::IonBuffer(IonBuffer&& other) : IonBuffer() {
67 *this = std::move(other);
68}
69
70IonBuffer& IonBuffer::operator=(IonBuffer&& other) {
Mark Urbanus8a71b132017-03-16 11:06:51 -070071 ALOGD_IF(TRACE, "IonBuffer::operator=: handle_=%p other.handle_=%p", handle(),
72 other.handle());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080073
74 if (this != &other) {
Mark Urbanus8a71b132017-03-16 11:06:51 -070075 buffer_ = other.buffer_;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080076 other.FreeHandle();
77 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080078 return *this;
79}
80
81void IonBuffer::FreeHandle() {
Mark Urbanus8a71b132017-03-16 11:06:51 -070082 if (buffer_.get()) {
83 // GraphicBuffer unregisters and cleans up the handle if needed
84 buffer_ = nullptr;
Corey Tabakacd52dd92017-04-07 18:03:57 -070085 producer_usage_ = 0;
86 consumer_usage_ = 0;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080087 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080088}
89
Corey Tabakacd52dd92017-04-07 18:03:57 -070090int IonBuffer::Alloc(uint32_t width, uint32_t height, uint32_t format,
91 uint32_t usage) {
92 return Alloc(width, height, format, usage, usage);
93}
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080094
Corey Tabakacd52dd92017-04-07 18:03:57 -070095int 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
Chris Forbes73feb062017-04-19 17:16:48 -0700103 // 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));
Corey Tabakacd52dd92017-04-07 18:03:57 -0700107 if (buffer->initCheck() != OK) {
Chia-I Wub42f1712017-03-21 13:15:39 -0700108 ALOGE("IonBuffer::Aloc: Failed to allocate buffer");
Corey Tabakacd52dd92017-04-07 18:03:57 -0700109 return -EINVAL;
110 } else {
111 buffer_ = buffer;
112 producer_usage_ = producer_usage;
113 consumer_usage_ = consumer_usage;
114 return 0;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800115 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800116}
117
Corey Tabakacd52dd92017-04-07 18:03:57 -0700118void 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) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800126 ALOGD_IF(TRACE,
Corey Tabakacd52dd92017-04-07 18:03:57 -0700127 "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);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800132}
133
Corey Tabakacd52dd92017-04-07 18:03:57 -0700134int 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) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800142 ATRACE_NAME("IonBuffer::Import1");
143 ALOGD_IF(
144 TRACE,
Corey Tabakacd52dd92017-04-07 18:03:57 -0700145 "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);
Mark Urbanus8a71b132017-03-16 11:06:51 -0700148 FreeHandle();
Chris Forbes73feb062017-04-19 17:16:48 -0700149 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);
Corey Tabakacd52dd92017-04-07 18:03:57 -0700155 if (buffer->initCheck() != OK) {
Chia-I Wub42f1712017-03-21 13:15:39 -0700156 ALOGE("IonBuffer::Import: Failed to import buffer");
Mark Urbanus8a71b132017-03-16 11:06:51 -0700157 return -EINVAL;
Corey Tabakacd52dd92017-04-07 18:03:57 -0700158 } else {
159 buffer_ = buffer;
160 producer_usage_ = producer_usage;
161 consumer_usage_ = consumer_usage;
162 return 0;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800163 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800164}
165
166int IonBuffer::Import(const int* fd_array, int fd_count, const int* int_array,
Corey Tabakacd52dd92017-04-07 18:03:57 -0700167 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) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800177 ATRACE_NAME("IonBuffer::Import2");
178 ALOGD_IF(TRACE,
Corey Tabakacd52dd92017-04-07 18:03:57 -0700179 "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);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800184
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
Corey Tabakacd52dd92017-04-07 18:03:57 -0700201 const int ret = Import(handle, width, height, stride, format, producer_usage,
202 consumer_usage);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800203 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
Corey Tabakacd52dd92017-04-07 18:03:57 -0700237 const int ret =
238 Import(handle, other->width(), other->height(), other->stride(),
239 other->format(), other->producer_usage(), other->consumer_usage());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800240 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
Corey Tabakacd52dd92017-04-07 18:03:57 -0700250int IonBuffer::Lock(uint32_t usage, int x, int y, int width, int height,
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800251 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",
Mark Urbanus8a71b132017-03-16 11:06:51 -0700256 handle(), usage, x, y, width, height, address);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800257
Corey Tabakacd52dd92017-04-07 18:03:57 -0700258 status_t err =
259 buffer_->lock(usage, Rect(x, y, x + width, y + height), address);
Mark Urbanus8a71b132017-03-16 11:06:51 -0700260 if (err != NO_ERROR)
261 return -EINVAL;
262 else
263 return 0;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800264}
265
Corey Tabakacd52dd92017-04-07 18:03:57 -0700266int IonBuffer::LockYUV(uint32_t usage, int x, int y, int width, int height,
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800267 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",
Mark Urbanus8a71b132017-03-16 11:06:51 -0700271 handle(), usage, x, y, width, height);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800272
Corey Tabakacd52dd92017-04-07 18:03:57 -0700273 status_t err =
274 buffer_->lockYCbCr(usage, Rect(x, y, x + width, y + height), yuv);
Mark Urbanus8a71b132017-03-16 11:06:51 -0700275 if (err != NO_ERROR)
276 return -EINVAL;
277 else
278 return 0;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800279}
280
281int IonBuffer::Unlock() {
282 ATRACE_NAME("IonBuffer::Unlock");
Mark Urbanus8a71b132017-03-16 11:06:51 -0700283 ALOGD_IF(TRACE, "IonBuffer::Unlock: handle=%p", handle());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800284
Mark Urbanus8a71b132017-03-16 11:06:51 -0700285 status_t err = buffer_->unlock();
286 if (err != NO_ERROR)
287 return -EINVAL;
288 else
289 return 0;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800290}
Corey Tabakacd52dd92017-04-07 18:03:57 -0700291} // namespace dvr
292} // namespace android