blob: 716ab42dfc823d6f3b5e810c9fc8553be95f190c [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,
Jiwen 'Steve' Cai044963e2017-05-01 22:43:21 -070021 uint64_t usage)
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080022 : IonBuffer() {
Jiwen 'Steve' Cai044963e2017-05-01 22:43:21 -070023 Alloc(width, height, format, usage);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080024}
25
Corey Tabakacd52dd92017-04-07 18:03:57 -070026IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
Jiwen 'Steve' Cai044963e2017-05-01 22:43:21 -070027 uint32_t stride, uint32_t format, uint64_t usage)
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080028 : IonBuffer(handle, width, height, 1, stride, 0, format, usage) {}
29
Corey Tabakacd52dd92017-04-07 18:03:57 -070030IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
31 uint32_t layer_count, uint32_t stride,
Jiwen 'Steve' Cai044963e2017-05-01 22:43:21 -070032 uint32_t layer_stride, uint32_t format, uint64_t usage)
Mark Urbanus8a71b132017-03-16 11:06:51 -070033 : buffer_(nullptr) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080034 ALOGD_IF(TRACE,
Corey Tabakacd52dd92017-04-07 18:03:57 -070035 "IonBuffer::IonBuffer: handle=%p width=%u height=%u layer_count=%u "
Jiwen 'Steve' Cai044963e2017-05-01 22:43:21 -070036 "stride=%u layer stride=%u format=%u usage=%" PRIx64,
Corey Tabakacd52dd92017-04-07 18:03:57 -070037 handle, width, height, layer_count, stride, layer_stride, format,
Jiwen 'Steve' Cai044963e2017-05-01 22:43:21 -070038 usage);
Mark Urbanus8a71b132017-03-16 11:06:51 -070039 if (handle != 0) {
Jiwen 'Steve' Cai044963e2017-05-01 22:43:21 -070040 Import(handle, width, height, stride, format, usage);
Mark Urbanus8a71b132017-03-16 11:06:51 -070041 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080042}
43
44IonBuffer::~IonBuffer() {
45 ALOGD_IF(TRACE,
Corey Tabakacd52dd92017-04-07 18:03:57 -070046 "IonBuffer::~IonBuffer: handle=%p width=%u height=%u stride=%u "
47 "format=%u usage=%x",
48 handle(), width(), height(), stride(), format(), usage());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080049 FreeHandle();
50}
51
52IonBuffer::IonBuffer(IonBuffer&& other) : IonBuffer() {
53 *this = std::move(other);
54}
55
56IonBuffer& IonBuffer::operator=(IonBuffer&& other) {
Mark Urbanus8a71b132017-03-16 11:06:51 -070057 ALOGD_IF(TRACE, "IonBuffer::operator=: handle_=%p other.handle_=%p", handle(),
58 other.handle());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080059
60 if (this != &other) {
Mark Urbanus8a71b132017-03-16 11:06:51 -070061 buffer_ = other.buffer_;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080062 other.FreeHandle();
63 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080064 return *this;
65}
66
67void IonBuffer::FreeHandle() {
Mark Urbanus8a71b132017-03-16 11:06:51 -070068 if (buffer_.get()) {
69 // GraphicBuffer unregisters and cleans up the handle if needed
70 buffer_ = nullptr;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080071 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080072}
73
Corey Tabakacd52dd92017-04-07 18:03:57 -070074int IonBuffer::Alloc(uint32_t width, uint32_t height, uint32_t format,
Jiwen 'Steve' Cai044963e2017-05-01 22:43:21 -070075 uint64_t usage) {
76 ALOGD_IF(TRACE,
77 "IonBuffer::Alloc: width=%u height=%u format=%u usage=%" PRIx64,
78 width, height, format, usage);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080079
Chris Forbes73feb062017-04-19 17:16:48 -070080 sp<GraphicBuffer> buffer = new GraphicBuffer(
Jiwen 'Steve' Cai044963e2017-05-01 22:43:21 -070081 width, height, format, kDefaultGraphicBufferLayerCount, usage);
Corey Tabakacd52dd92017-04-07 18:03:57 -070082 if (buffer->initCheck() != OK) {
Chia-I Wub42f1712017-03-21 13:15:39 -070083 ALOGE("IonBuffer::Aloc: Failed to allocate buffer");
Corey Tabakacd52dd92017-04-07 18:03:57 -070084 return -EINVAL;
85 } else {
86 buffer_ = buffer;
Corey Tabakacd52dd92017-04-07 18:03:57 -070087 return 0;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080088 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080089}
90
Corey Tabakacd52dd92017-04-07 18:03:57 -070091void IonBuffer::Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
Jiwen 'Steve' Cai044963e2017-05-01 22:43:21 -070092 uint32_t stride, uint32_t format, uint64_t usage) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080093 ALOGD_IF(TRACE,
Corey Tabakacd52dd92017-04-07 18:03:57 -070094 "IonBuffer::Reset: handle=%p width=%u height=%u stride=%u format=%u "
Jiwen 'Steve' Cai044963e2017-05-01 22:43:21 -070095 "usage=%" PRIx64,
96 handle, width, height, stride, format, usage);
97 Import(handle, width, height, stride, format, usage);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080098}
99
Corey Tabakacd52dd92017-04-07 18:03:57 -0700100int IonBuffer::Import(buffer_handle_t handle, uint32_t width, uint32_t height,
Jiwen 'Steve' Cai044963e2017-05-01 22:43:21 -0700101 uint32_t stride, uint32_t format, uint64_t usage) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800102 ATRACE_NAME("IonBuffer::Import1");
103 ALOGD_IF(
104 TRACE,
Corey Tabakacd52dd92017-04-07 18:03:57 -0700105 "IonBuffer::Import: handle=%p width=%u height=%u stride=%u format=%u "
Jiwen 'Steve' Cai044963e2017-05-01 22:43:21 -0700106 "usage=%" PRIx64,
107 handle, width, height, stride, format, usage);
Mark Urbanus8a71b132017-03-16 11:06:51 -0700108 FreeHandle();
Jiwen 'Steve' Cai044963e2017-05-01 22:43:21 -0700109 sp<GraphicBuffer> buffer = new GraphicBuffer(
110 handle, GraphicBuffer::TAKE_UNREGISTERED_HANDLE, width, height, format,
111 kDefaultGraphicBufferLayerCount, usage, stride);
Corey Tabakacd52dd92017-04-07 18:03:57 -0700112 if (buffer->initCheck() != OK) {
Chia-I Wub42f1712017-03-21 13:15:39 -0700113 ALOGE("IonBuffer::Import: Failed to import buffer");
Mark Urbanus8a71b132017-03-16 11:06:51 -0700114 return -EINVAL;
Corey Tabakacd52dd92017-04-07 18:03:57 -0700115 } else {
116 buffer_ = buffer;
Corey Tabakacd52dd92017-04-07 18:03:57 -0700117 return 0;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800118 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800119}
120
121int IonBuffer::Import(const int* fd_array, int fd_count, const int* int_array,
Corey Tabakacd52dd92017-04-07 18:03:57 -0700122 int int_count, uint32_t width, uint32_t height,
Jiwen 'Steve' Cai044963e2017-05-01 22:43:21 -0700123 uint32_t stride, uint32_t format, uint64_t usage) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800124 ATRACE_NAME("IonBuffer::Import2");
125 ALOGD_IF(TRACE,
Corey Tabakacd52dd92017-04-07 18:03:57 -0700126 "IonBuffer::Import: fd_count=%d int_count=%d width=%u height=%u "
Jiwen 'Steve' Cai044963e2017-05-01 22:43:21 -0700127 "stride=%u format=%u usage=%" PRIx64,
128 fd_count, int_count, width, height, stride, format, usage);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800129
130 if (fd_count < 0 || int_count < 0) {
131 ALOGE("IonBuffer::Import: invalid arguments.");
132 return -EINVAL;
133 }
134
135 native_handle_t* handle = native_handle_create(fd_count, int_count);
136 if (!handle) {
137 ALOGE("IonBuffer::Import: failed to create new native handle.");
138 return -ENOMEM;
139 }
140
141 // Copy fd_array into the first part of handle->data and int_array right
142 // after it.
143 memcpy(handle->data, fd_array, sizeof(int) * fd_count);
144 memcpy(handle->data + fd_count, int_array, sizeof(int) * int_count);
145
Jiwen 'Steve' Cai044963e2017-05-01 22:43:21 -0700146 const int ret = Import(handle, width, height, stride, format, usage);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800147 if (ret < 0) {
148 ALOGE("IonBuffer::Import: failed to import raw native handle: %s",
149 strerror(-ret));
150 native_handle_close(handle);
151 native_handle_delete(handle);
152 }
153
154 return ret;
155}
156
157int IonBuffer::Duplicate(const IonBuffer* other) {
158 if (!other->handle())
159 return -EINVAL;
160
161 const int fd_count = other->handle()->numFds;
162 const int int_count = other->handle()->numInts;
163
164 if (fd_count < 0 || int_count < 0)
165 return -EINVAL;
166
167 native_handle_t* handle = native_handle_create(fd_count, int_count);
168 if (!handle) {
169 ALOGE("IonBuffer::Duplicate: Failed to create new native handle.");
170 return -ENOMEM;
171 }
172
173 // Duplicate the file descriptors from the other native handle.
174 for (int i = 0; i < fd_count; i++)
175 handle->data[i] = dup(other->handle()->data[i]);
176
177 // Copy the ints after the file descriptors.
178 memcpy(handle->data + fd_count, other->handle()->data + fd_count,
179 sizeof(int) * int_count);
180
Corey Tabakacd52dd92017-04-07 18:03:57 -0700181 const int ret =
182 Import(handle, other->width(), other->height(), other->stride(),
Jiwen 'Steve' Cai044963e2017-05-01 22:43:21 -0700183 other->format(), other->usage());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800184 if (ret < 0) {
185 ALOGE("IonBuffer::Duplicate: Failed to import duplicate native handle: %s",
186 strerror(-ret));
187 native_handle_close(handle);
188 native_handle_delete(handle);
189 }
190
191 return ret;
192}
193
Corey Tabakacd52dd92017-04-07 18:03:57 -0700194int IonBuffer::Lock(uint32_t usage, int x, int y, int width, int height,
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800195 void** address) {
196 ATRACE_NAME("IonBuffer::Lock");
197 ALOGD_IF(TRACE,
198 "IonBuffer::Lock: handle=%p usage=%d x=%d y=%d width=%d height=%d "
199 "address=%p",
Mark Urbanus8a71b132017-03-16 11:06:51 -0700200 handle(), usage, x, y, width, height, address);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800201
Corey Tabakacd52dd92017-04-07 18:03:57 -0700202 status_t err =
203 buffer_->lock(usage, Rect(x, y, x + width, y + height), address);
Mark Urbanus8a71b132017-03-16 11:06:51 -0700204 if (err != NO_ERROR)
205 return -EINVAL;
206 else
207 return 0;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800208}
209
Corey Tabakacd52dd92017-04-07 18:03:57 -0700210int IonBuffer::LockYUV(uint32_t usage, int x, int y, int width, int height,
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800211 struct android_ycbcr* yuv) {
212 ATRACE_NAME("IonBuffer::LockYUV");
213 ALOGD_IF(TRACE,
214 "IonBuffer::Lock: handle=%p usage=%d x=%d y=%d width=%d height=%d",
Mark Urbanus8a71b132017-03-16 11:06:51 -0700215 handle(), usage, x, y, width, height);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800216
Corey Tabakacd52dd92017-04-07 18:03:57 -0700217 status_t err =
218 buffer_->lockYCbCr(usage, Rect(x, y, x + width, y + height), yuv);
Mark Urbanus8a71b132017-03-16 11:06:51 -0700219 if (err != NO_ERROR)
220 return -EINVAL;
221 else
222 return 0;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800223}
224
225int IonBuffer::Unlock() {
226 ATRACE_NAME("IonBuffer::Unlock");
Mark Urbanus8a71b132017-03-16 11:06:51 -0700227 ALOGD_IF(TRACE, "IonBuffer::Unlock: handle=%p", handle());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800228
Mark Urbanus8a71b132017-03-16 11:06:51 -0700229 status_t err = buffer_->unlock();
230 if (err != NO_ERROR)
231 return -EINVAL;
232 else
233 return 0;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800234}
Corey Tabakacd52dd92017-04-07 18:03:57 -0700235} // namespace dvr
236} // namespace android