blob: e5a56c1a4b61c958cdc300ff1fc52ef84c8e2b8a [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
9namespace android {
10namespace dvr {
11
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080012IonBuffer::IonBuffer() : IonBuffer(nullptr, 0, 0, 0, 0, 0, 0, 0) {}
13
14IonBuffer::IonBuffer(int width, int height, int format, int usage)
15 : IonBuffer() {
16 Alloc(width, height, format, usage);
17}
18
19IonBuffer::IonBuffer(buffer_handle_t handle, int width, int height, int stride,
20 int format, int usage)
21 : IonBuffer(handle, width, height, 1, stride, 0, format, usage) {}
22
Mark Urbanus8a71b132017-03-16 11:06:51 -070023
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080024IonBuffer::IonBuffer(buffer_handle_t handle, int width, int height,
25 int layer_count, int stride, int layer_stride, int format,
26 int usage)
Mark Urbanus8a71b132017-03-16 11:06:51 -070027 : buffer_(nullptr) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080028 ALOGD_IF(TRACE,
Mark Urbanus8a71b132017-03-16 11:06:51 -070029 "IonBuffer::IonBuffer: handle=%p width=%d height=%d layer_count=%d "
30 "stride=%d layer stride=%d format=%d usage=%d",
31 handle, width, height, layer_count, stride, layer_stride,
32 format, usage);
33 if (handle != 0) {
34 Import(handle, width, height, stride, format, usage);
35 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080036}
37
38IonBuffer::~IonBuffer() {
39 ALOGD_IF(TRACE,
40 "IonBuffer::~IonBuffer: handle=%p width=%d height=%d stride=%d "
41 "format=%d usage=%d",
Mark Urbanus8a71b132017-03-16 11:06:51 -070042 handle() , width(), height(), stride(), format(), usage());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080043 FreeHandle();
44}
45
46IonBuffer::IonBuffer(IonBuffer&& other) : IonBuffer() {
47 *this = std::move(other);
48}
49
50IonBuffer& IonBuffer::operator=(IonBuffer&& other) {
Mark Urbanus8a71b132017-03-16 11:06:51 -070051 ALOGD_IF(TRACE, "IonBuffer::operator=: handle_=%p other.handle_=%p", handle(),
52 other.handle());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080053
54 if (this != &other) {
Mark Urbanus8a71b132017-03-16 11:06:51 -070055 buffer_ = other.buffer_;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080056 other.FreeHandle();
57 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080058 return *this;
59}
60
61void IonBuffer::FreeHandle() {
Mark Urbanus8a71b132017-03-16 11:06:51 -070062 if (buffer_.get()) {
63 // GraphicBuffer unregisters and cleans up the handle if needed
64 buffer_ = nullptr;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080065 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080066}
67
68int IonBuffer::Alloc(int width, int height, int format, int usage) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080069 ALOGD_IF(TRACE, "IonBuffer::Alloc: width=%d height=%d format=%d usage=%d",
70 width, height, format, usage);
71
Mark Urbanus8a71b132017-03-16 11:06:51 -070072 buffer_ = new GraphicBuffer(width, height, format, usage);
Chia-I Wub42f1712017-03-21 13:15:39 -070073 if (buffer_->initCheck() != OK) {
74 ALOGE("IonBuffer::Aloc: Failed to allocate buffer");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080075 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080076 return 0;
77}
78
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080079void IonBuffer::Reset(buffer_handle_t handle, int width, int height, int stride,
80 int format, int usage) {
81 ALOGD_IF(TRACE,
82 "IonBuffer::Reset: handle=%p width=%d height=%d stride=%d format=%d "
83 "usage=%d",
84 handle, width, height, stride, format, usage);
Mark Urbanus8a71b132017-03-16 11:06:51 -070085 Import(handle, width, height, stride, format, usage);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080086}
87
88int IonBuffer::Import(buffer_handle_t handle, int width, int height, int stride,
89 int format, int usage) {
90 ATRACE_NAME("IonBuffer::Import1");
91 ALOGD_IF(
92 TRACE,
93 "IonBuffer::Import: handle=%p width=%d height=%d stride=%d format=%d "
94 "usage=%d",
95 handle, width, height, stride, format, usage);
Mark Urbanus8a71b132017-03-16 11:06:51 -070096 FreeHandle();
Chia-I Wub42f1712017-03-21 13:15:39 -070097 buffer_ = new GraphicBuffer(handle, GraphicBuffer::TAKE_UNREGISTERED_HANDLE,
98 width, height, format, 1, usage, stride);
99 if (buffer_->initCheck() != OK) {
100 ALOGE("IonBuffer::Import: Failed to import buffer");
Mark Urbanus8a71b132017-03-16 11:06:51 -0700101 return -EINVAL;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800102 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800103 return 0;
104}
105
106int IonBuffer::Import(const int* fd_array, int fd_count, const int* int_array,
107 int int_count, int width, int height, int stride,
108 int format, int usage) {
109 ATRACE_NAME("IonBuffer::Import2");
110 ALOGD_IF(TRACE,
111 "IonBuffer::Import: fd_count=%d int_count=%d width=%d height=%d "
112 "stride=%d format=%d usage=%d",
113 fd_count, int_count, width, height, stride, format, usage);
114
115 if (fd_count < 0 || int_count < 0) {
116 ALOGE("IonBuffer::Import: invalid arguments.");
117 return -EINVAL;
118 }
119
120 native_handle_t* handle = native_handle_create(fd_count, int_count);
121 if (!handle) {
122 ALOGE("IonBuffer::Import: failed to create new native handle.");
123 return -ENOMEM;
124 }
125
126 // Copy fd_array into the first part of handle->data and int_array right
127 // after it.
128 memcpy(handle->data, fd_array, sizeof(int) * fd_count);
129 memcpy(handle->data + fd_count, int_array, sizeof(int) * int_count);
130
131 int ret = Import(handle, width, height, stride, format, usage);
132 if (ret < 0) {
133 ALOGE("IonBuffer::Import: failed to import raw native handle: %s",
134 strerror(-ret));
135 native_handle_close(handle);
136 native_handle_delete(handle);
137 }
138
139 return ret;
140}
141
142int IonBuffer::Duplicate(const IonBuffer* other) {
143 if (!other->handle())
144 return -EINVAL;
145
146 const int fd_count = other->handle()->numFds;
147 const int int_count = other->handle()->numInts;
148
149 if (fd_count < 0 || int_count < 0)
150 return -EINVAL;
151
152 native_handle_t* handle = native_handle_create(fd_count, int_count);
153 if (!handle) {
154 ALOGE("IonBuffer::Duplicate: Failed to create new native handle.");
155 return -ENOMEM;
156 }
157
158 // Duplicate the file descriptors from the other native handle.
159 for (int i = 0; i < fd_count; i++)
160 handle->data[i] = dup(other->handle()->data[i]);
161
162 // Copy the ints after the file descriptors.
163 memcpy(handle->data + fd_count, other->handle()->data + fd_count,
164 sizeof(int) * int_count);
165
166 const int ret = Import(handle, other->width(), other->height(),
167 other->stride(), other->format(), other->usage());
168 if (ret < 0) {
169 ALOGE("IonBuffer::Duplicate: Failed to import duplicate native handle: %s",
170 strerror(-ret));
171 native_handle_close(handle);
172 native_handle_delete(handle);
173 }
174
175 return ret;
176}
177
178int IonBuffer::Lock(int usage, int x, int y, int width, int height,
179 void** address) {
180 ATRACE_NAME("IonBuffer::Lock");
181 ALOGD_IF(TRACE,
182 "IonBuffer::Lock: handle=%p usage=%d x=%d y=%d width=%d height=%d "
183 "address=%p",
Mark Urbanus8a71b132017-03-16 11:06:51 -0700184 handle(), usage, x, y, width, height, address);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800185
Mark Urbanus8a71b132017-03-16 11:06:51 -0700186 status_t err = buffer_->lock(usage, Rect(x, y, x + width, y + height),
187 address);
188 if (err != NO_ERROR)
189 return -EINVAL;
190 else
191 return 0;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800192}
193
194int IonBuffer::LockYUV(int usage, int x, int y, int width, int height,
195 struct android_ycbcr* yuv) {
196 ATRACE_NAME("IonBuffer::LockYUV");
197 ALOGD_IF(TRACE,
198 "IonBuffer::Lock: handle=%p usage=%d x=%d y=%d width=%d height=%d",
Mark Urbanus8a71b132017-03-16 11:06:51 -0700199 handle(), usage, x, y, width, height);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800200
Mark Urbanus8a71b132017-03-16 11:06:51 -0700201 status_t err = buffer_->lockYCbCr(usage, Rect(x, y, x + width, y + height),
202 yuv);
203 if (err != NO_ERROR)
204 return -EINVAL;
205 else
206 return 0;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800207}
208
209int IonBuffer::Unlock() {
210 ATRACE_NAME("IonBuffer::Unlock");
Mark Urbanus8a71b132017-03-16 11:06:51 -0700211 ALOGD_IF(TRACE, "IonBuffer::Unlock: handle=%p", handle());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800212
Mark Urbanus8a71b132017-03-16 11:06:51 -0700213 status_t err = buffer_->unlock();
214 if (err != NO_ERROR)
215 return -EINVAL;
216 else
217 return 0;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800218}
Mark Urbanus8a71b132017-03-16 11:06:51 -0700219} // namespace dvr
220} // namespace android