blob: 4db21647fda380afa234d04bdb408120fccbd642 [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
12gralloc_module_t const* IonBuffer::gralloc_module_ = nullptr;
13alloc_device_t* IonBuffer::gralloc_device_ = nullptr;
14
15IonBuffer::IonBuffer() : IonBuffer(nullptr, 0, 0, 0, 0, 0, 0, 0) {}
16
17IonBuffer::IonBuffer(int width, int height, int format, int usage)
18 : IonBuffer() {
19 Alloc(width, height, format, usage);
20}
21
22IonBuffer::IonBuffer(buffer_handle_t handle, int width, int height, int stride,
23 int format, int usage)
24 : IonBuffer(handle, width, height, 1, stride, 0, format, usage) {}
25
26IonBuffer::IonBuffer(buffer_handle_t handle, int width, int height,
27 int layer_count, int stride, int layer_stride, int format,
28 int usage)
29 : handle_(handle),
30 width_(width),
31 height_(height),
32 layer_count_(layer_count),
33 stride_(stride),
34 layer_stride_(layer_stride),
35 format_(format),
36 usage_(usage),
37 locked_(false),
38 needs_unregister_(false) {
39 ALOGD_IF(TRACE,
40 "IonBuffer::IonBuffer: handle=%p width=%d height=%d layer_count=%d "
41 "stride=%d layer stride=%d format=%d usage=%d",
42 handle_, width_, height_, layer_count_, stride_, layer_stride_,
43 format_, usage_);
44 GrallocInit();
45}
46
47IonBuffer::~IonBuffer() {
48 ALOGD_IF(TRACE,
49 "IonBuffer::~IonBuffer: handle=%p width=%d height=%d stride=%d "
50 "format=%d usage=%d",
51 handle_, width_, height_, stride_, format_, usage_);
52
53 FreeHandle();
54}
55
56IonBuffer::IonBuffer(IonBuffer&& other) : IonBuffer() {
57 *this = std::move(other);
58}
59
60IonBuffer& IonBuffer::operator=(IonBuffer&& other) {
61 ALOGD_IF(TRACE, "IonBuffer::operator=: handle_=%p other.handle_=%p", handle_,
62 other.handle_);
63
64 if (this != &other) {
65 Replace(other.handle_, other.width_, other.height_, other.layer_count_,
66 other.stride_, other.layer_stride_, other.format_, other.usage_,
67 other.needs_unregister_);
68 locked_ = other.locked_;
69 other.handle_ = nullptr;
70 other.FreeHandle();
71 }
72
73 return *this;
74}
75
76void IonBuffer::FreeHandle() {
77 if (handle_) {
78 // Lock/Unlock don't need to be balanced, but one Unlock is needed to
79 // clean/unmap the buffer. Warn if this didn't happen before freeing the
80 // native handle.
81 ALOGW_IF(locked_,
82 "IonBuffer::FreeHandle: freeing a locked handle!!! handle=%p",
83 handle_);
84
85 if (needs_unregister_) {
86 int ret = gralloc_module_->unregisterBuffer(gralloc_module_, handle_);
87 ALOGE_IF(ret < 0,
88 "IonBuffer::FreeHandle: Failed to unregister handle: %s",
89 strerror(-ret));
90
91 native_handle_close(const_cast<native_handle_t*>(handle_));
92 native_handle_delete(const_cast<native_handle_t*>(handle_));
93 } else {
94 int ret = gralloc_device_->free(gralloc_device_, handle_);
95 if (ret < 0) {
96 ALOGE("IonBuffer::FreeHandle: failed to free buffer: %s",
97 strerror(-ret));
98
99 // Not sure if this is the right thing to do. Attempting to prevent a
100 // memory leak of the native handle.
101 native_handle_close(const_cast<native_handle_t*>(handle_));
102 native_handle_delete(const_cast<native_handle_t*>(handle_));
103 }
104 }
105 }
106
107 // Always re-initialize these members, even if handle_ was nullptr, in case
108 // someone was dumb enough to pass a nullptr handle to the constructor or
109 // Reset.
110 handle_ = nullptr;
111 width_ = 0;
112 height_ = 0;
113 layer_count_ = 0;
114 stride_ = 0;
115 layer_stride_ = 0;
116 format_ = 0;
117 usage_ = 0;
118 locked_ = false;
119 needs_unregister_ = false;
120}
121
122int IonBuffer::Alloc(int width, int height, int format, int usage) {
123 ATRACE_NAME("IonBuffer::Alloc");
124 ALOGD_IF(TRACE, "IonBuffer::Alloc: width=%d height=%d format=%d usage=%d",
125 width, height, format, usage);
126
127 int stride;
128 buffer_handle_t handle;
129
130 int ret = gralloc_device_->alloc(gralloc_device_, width, height, format,
131 usage, &handle, &stride);
132 if (ret < 0) {
133 ALOGE("IonBuffer::Alloc: failed to allocate gralloc buffer: %s",
134 strerror(-ret));
135 return ret;
136 }
137
138 Replace(handle, width, height, 1, stride, 0, format, usage, false);
139 return 0;
140}
141
142void IonBuffer::Replace(buffer_handle_t handle, int width, int height,
143 int layer_count, int stride, int layer_stride,
144 int format, int usage, bool needs_unregister) {
145 FreeHandle();
146
147 handle_ = handle;
148 width_ = width;
149 height_ = height;
150 layer_count_ = layer_count;
151 stride_ = stride;
152 layer_stride_ = layer_stride;
153 format_ = format;
154 usage_ = usage;
155 needs_unregister_ = needs_unregister;
156}
157
158void IonBuffer::Reset(buffer_handle_t handle, int width, int height, int stride,
159 int format, int usage) {
160 ALOGD_IF(TRACE,
161 "IonBuffer::Reset: handle=%p width=%d height=%d stride=%d format=%d "
162 "usage=%d",
163 handle, width, height, stride, format, usage);
164
165 Replace(handle, width, height, 1, stride, 0, format, usage, false);
166}
167
168int IonBuffer::Import(buffer_handle_t handle, int width, int height, int stride,
169 int format, int usage) {
170 ATRACE_NAME("IonBuffer::Import1");
171 ALOGD_IF(
172 TRACE,
173 "IonBuffer::Import: handle=%p width=%d height=%d stride=%d format=%d "
174 "usage=%d",
175 handle, width, height, stride, format, usage);
176
177 int ret = gralloc_module_->registerBuffer(gralloc_module_, handle);
178 if (ret < 0) {
179 ALOGE("IonBuffer::Import: failed to import handle: %s", strerror(-ret));
180 return ret;
181 }
182
183 Replace(handle, width, height, 1, stride, 0, format, usage, true);
184 return 0;
185}
186
187int IonBuffer::Import(const int* fd_array, int fd_count, const int* int_array,
188 int int_count, int width, int height, int stride,
189 int format, int usage) {
190 ATRACE_NAME("IonBuffer::Import2");
191 ALOGD_IF(TRACE,
192 "IonBuffer::Import: fd_count=%d int_count=%d width=%d height=%d "
193 "stride=%d format=%d usage=%d",
194 fd_count, int_count, width, height, stride, format, usage);
195
196 if (fd_count < 0 || int_count < 0) {
197 ALOGE("IonBuffer::Import: invalid arguments.");
198 return -EINVAL;
199 }
200
201 native_handle_t* handle = native_handle_create(fd_count, int_count);
202 if (!handle) {
203 ALOGE("IonBuffer::Import: failed to create new native handle.");
204 return -ENOMEM;
205 }
206
207 // Copy fd_array into the first part of handle->data and int_array right
208 // after it.
209 memcpy(handle->data, fd_array, sizeof(int) * fd_count);
210 memcpy(handle->data + fd_count, int_array, sizeof(int) * int_count);
211
212 int ret = Import(handle, width, height, stride, format, usage);
213 if (ret < 0) {
214 ALOGE("IonBuffer::Import: failed to import raw native handle: %s",
215 strerror(-ret));
216 native_handle_close(handle);
217 native_handle_delete(handle);
218 }
219
220 return ret;
221}
222
223int IonBuffer::Duplicate(const IonBuffer* other) {
224 if (!other->handle())
225 return -EINVAL;
226
227 const int fd_count = other->handle()->numFds;
228 const int int_count = other->handle()->numInts;
229
230 if (fd_count < 0 || int_count < 0)
231 return -EINVAL;
232
233 native_handle_t* handle = native_handle_create(fd_count, int_count);
234 if (!handle) {
235 ALOGE("IonBuffer::Duplicate: Failed to create new native handle.");
236 return -ENOMEM;
237 }
238
239 // Duplicate the file descriptors from the other native handle.
240 for (int i = 0; i < fd_count; i++)
241 handle->data[i] = dup(other->handle()->data[i]);
242
243 // Copy the ints after the file descriptors.
244 memcpy(handle->data + fd_count, other->handle()->data + fd_count,
245 sizeof(int) * int_count);
246
247 const int ret = Import(handle, other->width(), other->height(),
248 other->stride(), other->format(), other->usage());
249 if (ret < 0) {
250 ALOGE("IonBuffer::Duplicate: Failed to import duplicate native handle: %s",
251 strerror(-ret));
252 native_handle_close(handle);
253 native_handle_delete(handle);
254 }
255
256 return ret;
257}
258
259int IonBuffer::Lock(int usage, int x, int y, int width, int height,
260 void** address) {
261 ATRACE_NAME("IonBuffer::Lock");
262 ALOGD_IF(TRACE,
263 "IonBuffer::Lock: handle=%p usage=%d x=%d y=%d width=%d height=%d "
264 "address=%p",
265 handle_, usage, x, y, width, height, address);
266
267 // Lock may be called multiple times; but only one Unlock is required.
268 const int err = gralloc_module_->lock(gralloc_module_, handle_, usage, x, y,
269 width, height, address);
270 if (!err)
271 locked_ = true;
272
273 return err;
274}
275
276int IonBuffer::LockYUV(int usage, int x, int y, int width, int height,
277 struct android_ycbcr* yuv) {
278 ATRACE_NAME("IonBuffer::LockYUV");
279 ALOGD_IF(TRACE,
280 "IonBuffer::Lock: handle=%p usage=%d x=%d y=%d width=%d height=%d",
281 handle_, usage, x, y, width, height);
282 const int err = gralloc_module_->lock_ycbcr(gralloc_module_, handle_, usage,
283 x, y, width, height, yuv);
284 if (!err)
285 locked_ = true;
286
287 return err;
288}
289
290int IonBuffer::Unlock() {
291 ATRACE_NAME("IonBuffer::Unlock");
292 ALOGD_IF(TRACE, "IonBuffer::Unlock: handle=%p", handle_);
293
294 // Lock may be called multiple times; but only one Unlock is required.
295 const int err = gralloc_module_->unlock(gralloc_module_, handle_);
296 if (!err)
297 locked_ = false;
298
299 return err;
300}
301
302void IonBuffer::GrallocInit() {
303 static std::once_flag gralloc_flag;
304 std::call_once(gralloc_flag, []() {
305 hw_module_t const* module = nullptr;
306 alloc_device_t* device = nullptr;
307
308 int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
309 ALOGE_IF(err, "IonBuffer::GrallocInit: failed to find the %s module: %s",
310 GRALLOC_HARDWARE_MODULE_ID, strerror(-err));
311
312 err = gralloc_open(module, &device);
313 ALOGE_IF(err, "IonBuffer::GrallocInit: failed to open gralloc device: %s",
314 strerror(-err));
315
316 gralloc_module_ = reinterpret_cast<gralloc_module_t const*>(module);
317 gralloc_device_ = device;
318 });
319}
320
321} // namespace dvr
322} // namespace android