blob: ec07ce0ee5f27af8b18fe9da173cd9b54d51b625 [file] [log] [blame]
Naseer Ahmede36f2242017-12-01 15:33:56 -05001/*
2 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
31#define DEBUG 0
32#include "QtiMapper.h"
33#include <cutils/trace.h>
34#include <qdMetaData.h>
35#include <sync/sync.h>
36#include "gr_utils.h"
37
38namespace vendor {
39namespace qti {
40namespace hardware {
41namespace display {
42namespace mapper {
43namespace V1_0 {
44namespace implementation {
45
46using gralloc::BufferInfo;
47
48QtiMapper::QtiMapper() {
49 buf_mgr_ = BufferManager::GetInstance();
50 ALOGD_IF(DEBUG, "Created QtiMapper instance");
51}
52
53bool QtiMapper::ValidDescriptor(const IMapper::BufferDescriptorInfo &bd) {
54 if (bd.width == 0 || bd.height == 0 || (static_cast<int32_t>(bd.format) <= 0) ||
55 bd.layerCount != 1) {
56 return false;
57 }
58
59 return true;
60}
61
62// Methods from ::android::hardware::graphics::mapper::V2_0::IMapper follow.
63Return<void> QtiMapper::createDescriptor(const IMapper::BufferDescriptorInfo &descriptor_info,
64 createDescriptor_cb hidl_cb) {
65 ALOGD_IF(DEBUG,
66 "BufferDescriptorInfo: wxh: %dx%d usage: 0x%" PRIu64 " format: %d layer_count: %d",
67 descriptor_info.width, descriptor_info.height, descriptor_info.usage,
68 static_cast<uint32_t>(descriptor_info.format), descriptor_info.layerCount);
69
70 if (ValidDescriptor(descriptor_info)) {
71 auto vec = gralloc::BufferDescriptor::Encode(descriptor_info);
72 hidl_cb(Error::NONE, vec);
73 } else {
74 hidl_cb(Error::BAD_VALUE, hidl_vec<uint32_t>());
75 }
76 return Void();
77}
78
79Return<void> QtiMapper::importBuffer(const hidl_handle &raw_handle, importBuffer_cb hidl_cb) {
80 if (!raw_handle.getNativeHandle()) {
81 ALOGE("%s: Unable to import handle", __FUNCTION__);
82 hidl_cb(Error::BAD_BUFFER, nullptr);
83 return Void();
84 }
85
86 native_handle_t *buffer_handle = native_handle_clone(raw_handle.getNativeHandle());
87 if (!buffer_handle) {
88 ALOGE("%s: Unable to clone handle", __FUNCTION__);
89 hidl_cb(Error::NO_RESOURCES, nullptr);
90 return Void();
91 }
92
93 auto error = buf_mgr_->RetainBuffer(PRIV_HANDLE_CONST(buffer_handle));
94 if (error != Error::NONE) {
95 ALOGE("%s: Unable to retain handle: %p", __FUNCTION__, buffer_handle);
96 native_handle_close(buffer_handle);
97 native_handle_delete(buffer_handle);
98
99 hidl_cb(error, nullptr);
100 return Void();
101 }
102 ALOGD_IF(DEBUG, "Imported handle: %p id: %" PRIu64, buffer_handle,
103 PRIV_HANDLE_CONST(buffer_handle)->id);
104 hidl_cb(Error::NONE, buffer_handle);
105 return Void();
106}
107
108Return<Error> QtiMapper::freeBuffer(void *buffer) {
109 if (!buffer) {
110 return Error::BAD_BUFFER;
111 }
112 return buf_mgr_->ReleaseBuffer(PRIV_HANDLE_CONST(buffer));
113}
114
115bool QtiMapper::GetFenceFd(const hidl_handle &fence_handle, int *outFenceFd) {
116 auto handle = fence_handle.getNativeHandle();
117 if (handle && handle->numFds > 1) {
118 ALOGE("invalid fence handle with %d fds", handle->numFds);
119 return false;
120 }
121
122 *outFenceFd = (handle && handle->numFds == 1) ? handle->data[0] : -1;
123 return true;
124}
125
126void QtiMapper::WaitFenceFd(int fence_fd) {
127 if (fence_fd < 0) {
128 return;
129 }
130
131 const int timeout = 3000;
132 ATRACE_BEGIN("fence wait");
133 const int error = sync_wait(fence_fd, timeout);
134 ATRACE_END();
135 if (error < 0) {
136 ALOGE("QtiMapper: lock fence %d didn't signal in %u ms - error: %s", fence_fd, timeout,
137 strerror(errno));
138 }
139}
140
141Error QtiMapper::LockBuffer(void *buffer, uint64_t usage, const hidl_handle &acquire_fence) {
142 if (!buffer) {
143 return Error::BAD_BUFFER;
144 }
145
146 int fence_fd;
147 if (!GetFenceFd(acquire_fence, &fence_fd)) {
148 return Error::BAD_VALUE;
149 }
150
151 if (fence_fd > 0) {
152 WaitFenceFd(fence_fd);
153 }
154
155 auto hnd = PRIV_HANDLE_CONST(buffer);
156
157 return buf_mgr_->LockBuffer(hnd, usage);
158}
159
160Return<void> QtiMapper::lock(void *buffer, uint64_t cpu_usage,
161 const IMapper::Rect & /*access_region*/,
162 const hidl_handle &acquire_fence, lock_cb hidl_cb) {
163 auto err = LockBuffer(buffer, cpu_usage, acquire_fence);
164 if (err != Error::NONE) {
165 hidl_cb(err, nullptr);
166 return Void();
167 }
168
169 auto hnd = PRIV_HANDLE_CONST(buffer);
170 auto *out_data = reinterpret_cast<void *>(hnd->base);
171 hidl_cb(Error::NONE, out_data);
172 return Void();
173}
174
175Return<void> QtiMapper::lockYCbCr(void *buffer, uint64_t cpu_usage,
176 const IMapper::Rect & /*access_region*/,
177 const hidl_handle &acquire_fence, lockYCbCr_cb hidl_cb) {
178 YCbCrLayout layout = {};
179 auto err = LockBuffer(buffer, cpu_usage, acquire_fence);
180 if (err != Error::NONE) {
181 hidl_cb(err, layout);
182 return Void();
183 }
184
185 auto hnd = PRIV_HANDLE_CONST(buffer);
186 android_ycbcr yuv_plane_info[2];
187 if (gralloc::GetYUVPlaneInfo(hnd, yuv_plane_info) != 0) {
188 hidl_cb(Error::BAD_VALUE, layout);
189 }
190 layout.y = yuv_plane_info[0].y;
191 layout.cr = yuv_plane_info[0].cr;
192 layout.cb = yuv_plane_info[0].cb;
193 layout.yStride = static_cast<uint32_t>(yuv_plane_info[0].ystride);
194 layout.cStride = static_cast<uint32_t>(yuv_plane_info[0].cstride);
195 layout.chromaStep = static_cast<uint32_t>(yuv_plane_info[0].chroma_step);
196 hidl_cb(Error::NONE, layout);
197 return Void();
198}
199
200Return<void> QtiMapper::unlock(void *buffer, unlock_cb hidl_cb) {
201 auto err = Error::BAD_BUFFER;
202 if (buffer != nullptr) {
203 err = buf_mgr_->UnlockBuffer(PRIV_HANDLE_CONST(buffer));
204 }
205 // We don't have a release fence
206 hidl_cb(err, hidl_handle(nullptr));
207 return Void();
208}
209
210Return<void> QtiMapper::getMapSecureBufferFlag(void *buffer, getMapSecureBufferFlag_cb hidl_cb) {
211 auto err = Error::BAD_BUFFER;
212 auto hnd = static_cast<private_handle_t *>(buffer);
213 int *map_secure_buffer = 0;
214 if (buffer != nullptr && private_handle_t::validate(hnd) != 0) {
215 if (getMetaData(hnd, GET_MAP_SECURE_BUFFER, map_secure_buffer) != 0) {
216 *map_secure_buffer = 0;
217 } else {
218 err = Error::NONE;
219 }
220 }
221 hidl_cb(err, *map_secure_buffer != 0);
222 return Void();
223}
224
225Return<void> QtiMapper::getInterlacedFlag(void *buffer, getInterlacedFlag_cb hidl_cb) {
226 auto err = Error::BAD_BUFFER;
227 auto hnd = static_cast<private_handle_t *>(buffer);
228 int *interlaced_flag = nullptr;
229 if (buffer != nullptr && private_handle_t::validate(hnd) != 0) {
230 if (getMetaData(hnd, GET_PP_PARAM_INTERLACED, interlaced_flag) != 0) {
231 *interlaced_flag = 0;
232 } else {
233 err = Error::NONE;
234 }
235 }
236 hidl_cb(err, *interlaced_flag != 0);
237 return Void();
238}
239
240Return<void> QtiMapper::getCustomDimensions(void *buffer, getCustomDimensions_cb hidl_cb) {
241 auto err = Error::BAD_BUFFER;
242 auto hnd = static_cast<private_handle_t *>(buffer);
243 int stride = 0;
244 int height = 0;
245 if (buffer != nullptr && private_handle_t::validate(hnd) != 0) {
246 stride = hnd->width;
247 height = hnd->height;
248 gralloc::GetCustomDimensions(hnd, &stride, &height);
249 err = Error::NONE;
250 }
251 hidl_cb(err, stride, height);
252 return Void();
253}
254
255Return<void> QtiMapper::getRgbDataAddress(void *buffer, getRgbDataAddress_cb hidl_cb) {
256 auto err = Error::BAD_BUFFER;
257 auto hnd = static_cast<private_handle_t *>(buffer);
258 void *rgb_data = nullptr;
259 if (buffer != nullptr && private_handle_t::validate(hnd) != 0) {
260 if (gralloc::GetRgbDataAddress(hnd, &rgb_data) == 0) {
261 err = Error::NONE;
262 }
263 }
264 hidl_cb(err, rgb_data);
265 return Void();
266}
267
268Return<void> QtiMapper::calculateBufferAttributes(int32_t width, int32_t height, int32_t format,
269 uint64_t usage,
270 calculateBufferAttributes_cb hidl_cb) {
271 unsigned int alignedw, alignedh;
272 BufferInfo info(width, height, format, usage);
273 gralloc::GetAlignedWidthAndHeight(info, &alignedw, &alignedh);
274 bool ubwc_enabled = gralloc::IsUBwcEnabled(format, usage);
275 hidl_cb(Error::NONE, alignedw, alignedh, ubwc_enabled);
276 return Void();
277}
278
279Return<void> QtiMapper::getColorSpace(void *buffer, getColorSpace_cb hidl_cb) {
280 auto err = Error::BAD_BUFFER;
281 auto hnd = static_cast<private_handle_t *>(buffer);
282 int color_space = 0;
283 if (buffer != nullptr && private_handle_t::validate(hnd) != 0) {
284 gralloc::GetColorSpaceFromMetadata(hnd, &color_space);
285 err = Error::NONE;
286 }
287 hidl_cb(err, color_space);
288 return Void();
289}
290
291Return<void> QtiMapper::getYuvPlaneInfo(void *buffer, getYuvPlaneInfo_cb hidl_cb) {
292 auto err = Error::BAD_BUFFER;
293 auto hnd = static_cast<private_handle_t *>(buffer);
294 hidl_vec<YCbCrLayout> layout;
295 layout.resize(2);
296 android_ycbcr yuv_plane_info[2];
297 if (buffer != nullptr && private_handle_t::validate(hnd) != 0) {
298 if (gralloc::GetYUVPlaneInfo(hnd, yuv_plane_info) == 0) {
299 err = Error::NONE;
300 for (int i=0; i < 2; i++) {
301 layout[i].y = yuv_plane_info[i].y;
302 layout[i].cr = yuv_plane_info[i].cr;
303 layout[i].cb = yuv_plane_info[i].cb;
304 layout[i].yStride = static_cast<uint32_t>(yuv_plane_info[i].ystride);
305 layout[i].cStride = static_cast<uint32_t>(yuv_plane_info[i].cstride);
306 layout[i].chromaStep = static_cast<uint32_t>(yuv_plane_info[i].chroma_step);
307 }
308 }
309 }
310 hidl_cb(err, layout);
311 return Void();
312}
313
314Return<Error> QtiMapper::setSingleBufferMode(void *buffer, bool enable) {
315 auto err = Error::BAD_BUFFER;
316 auto hnd = static_cast<private_handle_t *>(buffer);
317 if (buffer != nullptr && private_handle_t::validate(hnd) != 0) {
318 if (setMetaData(hnd, SET_SINGLE_BUFFER_MODE, &enable) != 0) {
319 err = Error::UNSUPPORTED;
320 } else {
321 err = Error::NONE;
322 }
323 }
324 return err;
325}
326
327// Methods from ::android::hidl::base::V1_0::IBase follow.
328
329// When we are in passthrough mode, this method is used
330// by hidl to obtain the SP HAL object
331IMapper *HIDL_FETCH_IMapper(const char * /* name */) {
332 ALOGD_IF(DEBUG, "Fetching IMapper from QtiMapper");
333 auto mapper = new QtiMapper();
334 return static_cast<IMapper *>(mapper);
335}
336
337IQtiMapper *HIDL_FETCH_IQtiMapper(const char * /* name */) {
338 ALOGD_IF(DEBUG, "Fetching QtiMapper");
339 return new QtiMapper();
340}
341} // namespace implementation
342} // namespace V1_0
343} // namespace mapper
344} // namespace display
345} // namespace hardware
346} // namespace qti
347} // namespace vendor