blob: dc105c095c1bf88bf6e8223ad232171b8d2e13ae [file] [log] [blame]
Marissa Wall87c8ba72019-06-20 14:20:52 -07001/*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "Gralloc4"
18
19#include <hidl/ServiceManagement.h>
20#include <hwbinder/IPCThreadState.h>
21#include <ui/Gralloc4.h>
22
23#include <inttypes.h>
24#include <log/log.h>
25#pragma clang diagnostic push
26#pragma clang diagnostic ignored "-Wzero-length-array"
27#include <sync/sync.h>
28#pragma clang diagnostic pop
29
30using android::hardware::graphics::allocator::V4_0::IAllocator;
31using android::hardware::graphics::common::V1_2::BufferUsage;
32using android::hardware::graphics::mapper::V4_0::BufferDescriptor;
33using android::hardware::graphics::mapper::V4_0::Error;
34using android::hardware::graphics::mapper::V4_0::IMapper;
35using android::hardware::graphics::mapper::V4_0::YCbCrLayout;
36
37namespace android {
38
39namespace {
40
41static constexpr Error kTransactionError = Error::NO_RESOURCES;
42
43uint64_t getValidUsageBits() {
44 static const uint64_t validUsageBits = []() -> uint64_t {
45 uint64_t bits = 0;
46 for (const auto bit :
47 hardware::hidl_enum_range<hardware::graphics::common::V1_2::BufferUsage>()) {
48 bits = bits | bit;
49 }
50 return bits;
51 }();
52 return validUsageBits;
53}
54
55static inline IMapper::Rect sGralloc4Rect(const Rect& rect) {
56 IMapper::Rect outRect{};
57 outRect.left = rect.left;
58 outRect.top = rect.top;
59 outRect.width = rect.width();
60 outRect.height = rect.height();
61 return outRect;
62}
63static inline void sBufferDescriptorInfo(uint32_t width, uint32_t height,
64 android::PixelFormat format, uint32_t layerCount,
65 uint64_t usage,
66 IMapper::BufferDescriptorInfo* outDescriptorInfo) {
67 outDescriptorInfo->width = width;
68 outDescriptorInfo->height = height;
69 outDescriptorInfo->layerCount = layerCount;
70 outDescriptorInfo->format = static_cast<hardware::graphics::common::V1_2::PixelFormat>(format);
71 outDescriptorInfo->usage = usage;
72}
73
74} // anonymous namespace
75
76void Gralloc4Mapper::preload() {
77 android::hardware::preloadPassthroughService<IMapper>();
78}
79
80Gralloc4Mapper::Gralloc4Mapper() {
81 mMapper = IMapper::getService();
82 if (mMapper == nullptr) {
83 ALOGI("mapper 4.x is not supported");
84 return;
85 }
86 if (mMapper->isRemote()) {
87 LOG_ALWAYS_FATAL("gralloc-mapper must be in passthrough mode");
88 }
89}
90
91bool Gralloc4Mapper::isLoaded() const {
92 return mMapper != nullptr;
93}
94
95status_t Gralloc4Mapper::validateBufferDescriptorInfo(
96 IMapper::BufferDescriptorInfo* descriptorInfo) const {
97 uint64_t validUsageBits = getValidUsageBits();
98
99 if (descriptorInfo->usage & ~validUsageBits) {
100 ALOGE("buffer descriptor contains invalid usage bits 0x%" PRIx64,
101 descriptorInfo->usage & ~validUsageBits);
102 return BAD_VALUE;
103 }
104 return NO_ERROR;
105}
106
107status_t Gralloc4Mapper::createDescriptor(void* bufferDescriptorInfo,
108 void* outBufferDescriptor) const {
109 IMapper::BufferDescriptorInfo* descriptorInfo =
110 static_cast<IMapper::BufferDescriptorInfo*>(bufferDescriptorInfo);
111 BufferDescriptor* outDescriptor = static_cast<BufferDescriptor*>(outBufferDescriptor);
112
113 status_t status = validateBufferDescriptorInfo(descriptorInfo);
114 if (status != NO_ERROR) {
115 return status;
116 }
117
118 Error error;
119 auto hidl_cb = [&](const auto& tmpError, const auto& tmpDescriptor) {
120 error = tmpError;
121 if (error != Error::NONE) {
122 return;
123 }
124 *outDescriptor = tmpDescriptor;
125 };
126
127 hardware::Return<void> ret = mMapper->createDescriptor(*descriptorInfo, hidl_cb);
128
129 return static_cast<status_t>((ret.isOk()) ? error : kTransactionError);
130}
131
132status_t Gralloc4Mapper::importBuffer(const hardware::hidl_handle& rawHandle,
133 buffer_handle_t* outBufferHandle) const {
134 Error error;
135 auto ret = mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
136 error = tmpError;
137 if (error != Error::NONE) {
138 return;
139 }
140 *outBufferHandle = static_cast<buffer_handle_t>(tmpBuffer);
141 });
142
143 return static_cast<status_t>((ret.isOk()) ? error : kTransactionError);
144}
145
146void Gralloc4Mapper::freeBuffer(buffer_handle_t bufferHandle) const {
147 auto buffer = const_cast<native_handle_t*>(bufferHandle);
148 auto ret = mMapper->freeBuffer(buffer);
149
150 auto error = (ret.isOk()) ? static_cast<Error>(ret) : kTransactionError;
151 ALOGE_IF(error != Error::NONE, "freeBuffer(%p) failed with %d", buffer, error);
152}
153
154status_t Gralloc4Mapper::validateBufferSize(buffer_handle_t bufferHandle, uint32_t width,
155 uint32_t height, android::PixelFormat format,
156 uint32_t layerCount, uint64_t usage,
157 uint32_t stride) const {
158 IMapper::BufferDescriptorInfo descriptorInfo;
159 sBufferDescriptorInfo(width, height, format, layerCount, usage, &descriptorInfo);
160
161 auto buffer = const_cast<native_handle_t*>(bufferHandle);
162 auto ret = mMapper->validateBufferSize(buffer, descriptorInfo, stride);
163
164 return static_cast<status_t>((ret.isOk()) ? static_cast<Error>(ret) : kTransactionError);
165}
166
167void Gralloc4Mapper::getTransportSize(buffer_handle_t bufferHandle, uint32_t* outNumFds,
168 uint32_t* outNumInts) const {
169 *outNumFds = uint32_t(bufferHandle->numFds);
170 *outNumInts = uint32_t(bufferHandle->numInts);
171
172 Error error;
173 auto buffer = const_cast<native_handle_t*>(bufferHandle);
174 auto ret = mMapper->getTransportSize(buffer,
175 [&](const auto& tmpError, const auto& tmpNumFds,
176 const auto& tmpNumInts) {
177 error = tmpError;
178 if (error != Error::NONE) {
179 return;
180 }
181 *outNumFds = tmpNumFds;
182 *outNumInts = tmpNumInts;
183 });
184
185 error = (ret.isOk()) ? error : kTransactionError;
186
187 ALOGE_IF(error != Error::NONE, "getTransportSize(%p) failed with %d", buffer, error);
188}
189
190status_t Gralloc4Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds,
191 int acquireFence, void** outData, int32_t* outBytesPerPixel,
192 int32_t* outBytesPerStride) const {
193 auto buffer = const_cast<native_handle_t*>(bufferHandle);
194
195 IMapper::Rect accessRegion = sGralloc4Rect(bounds);
196
197 // put acquireFence in a hidl_handle
198 hardware::hidl_handle acquireFenceHandle;
199 NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
200 if (acquireFence >= 0) {
201 auto h = native_handle_init(acquireFenceStorage, 1, 0);
202 h->data[0] = acquireFence;
203 acquireFenceHandle = h;
204 }
205
206 Error error;
207 auto ret = mMapper->lock(buffer, usage, accessRegion, acquireFenceHandle,
208 [&](const auto& tmpError, const auto& tmpData,
209 const auto& tmpBytesPerPixel, const auto& tmpBytesPerStride) {
210 error = tmpError;
211 if (error != Error::NONE) {
212 return;
213 }
214 *outData = tmpData;
215 if (outBytesPerPixel) {
216 *outBytesPerPixel = tmpBytesPerPixel;
217 }
218 if (outBytesPerStride) {
219 *outBytesPerStride = tmpBytesPerStride;
220 }
221 });
222
223 // we own acquireFence even on errors
224 if (acquireFence >= 0) {
225 close(acquireFence);
226 }
227
228 error = (ret.isOk()) ? error : kTransactionError;
229
230 ALOGW_IF(error != Error::NONE, "lock(%p, ...) failed: %d", bufferHandle, error);
231
232 return static_cast<status_t>(error);
233}
234
235status_t Gralloc4Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds,
236 int acquireFence, android_ycbcr* ycbcr) const {
237 auto buffer = const_cast<native_handle_t*>(bufferHandle);
238
239 IMapper::Rect accessRegion = sGralloc4Rect(bounds);
240
241 // put acquireFence in a hidl_handle
242 hardware::hidl_handle acquireFenceHandle;
243 NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
244 if (acquireFence >= 0) {
245 auto h = native_handle_init(acquireFenceStorage, 1, 0);
246 h->data[0] = acquireFence;
247 acquireFenceHandle = h;
248 }
249
250 YCbCrLayout layout;
251 Error error;
252 auto ret = mMapper->lockYCbCr(buffer, usage, accessRegion, acquireFenceHandle,
253 [&](const auto& tmpError, const auto& tmpLayout) {
254 error = tmpError;
255 if (error != Error::NONE) {
256 return;
257 }
258
259 layout = tmpLayout;
260 });
261
262 if (error == Error::NONE) {
263 ycbcr->y = layout.y;
264 ycbcr->cb = layout.cb;
265 ycbcr->cr = layout.cr;
266 ycbcr->ystride = static_cast<size_t>(layout.yStride);
267 ycbcr->cstride = static_cast<size_t>(layout.cStride);
268 ycbcr->chroma_step = static_cast<size_t>(layout.chromaStep);
269 }
270
271 // we own acquireFence even on errors
272 if (acquireFence >= 0) {
273 close(acquireFence);
274 }
275
276 return static_cast<status_t>((ret.isOk()) ? error : kTransactionError);
277}
278
279int Gralloc4Mapper::unlock(buffer_handle_t bufferHandle) const {
280 auto buffer = const_cast<native_handle_t*>(bufferHandle);
281
282 int releaseFence = -1;
283 Error error;
284 auto ret = mMapper->unlock(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
285 error = tmpError;
286 if (error != Error::NONE) {
287 return;
288 }
289
290 auto fenceHandle = tmpReleaseFence.getNativeHandle();
291 if (fenceHandle && fenceHandle->numFds == 1) {
292 int fd = dup(fenceHandle->data[0]);
293 if (fd >= 0) {
294 releaseFence = fd;
295 } else {
296 ALOGD("failed to dup unlock release fence");
297 sync_wait(fenceHandle->data[0], -1);
298 }
299 }
300 });
301
302 if (!ret.isOk()) {
303 error = kTransactionError;
304 }
305
306 if (error != Error::NONE) {
307 ALOGE("unlock(%p) failed with %d", buffer, error);
308 }
309
310 return releaseFence;
311}
312
313status_t Gralloc4Mapper::isSupported(uint32_t width, uint32_t height, android::PixelFormat format,
314 uint32_t layerCount, uint64_t usage,
315 bool* outSupported) const {
316 IMapper::BufferDescriptorInfo descriptorInfo;
317 sBufferDescriptorInfo(width, height, format, layerCount, usage, &descriptorInfo);
318
319 Error error;
320 auto ret = mMapper->isSupported(descriptorInfo,
321 [&](const auto& tmpError, const auto& tmpSupported) {
322 error = tmpError;
323 if (error != Error::NONE) {
324 return;
325 }
326 if (outSupported) {
327 *outSupported = tmpSupported;
328 }
329 });
330
331 if (!ret.isOk()) {
332 error = kTransactionError;
333 }
334
335 if (error != Error::NONE) {
336 ALOGE("isSupported(%u, %u, %d, %u, ...) failed with %d", width, height, format, layerCount,
337 error);
338 }
339
340 return static_cast<status_t>(error);
341}
342
343Gralloc4Allocator::Gralloc4Allocator(const Gralloc4Mapper& mapper) : mMapper(mapper) {
344 mAllocator = IAllocator::getService();
345 if (mAllocator == nullptr) {
346 ALOGW("allocator 3.x is not supported");
347 return;
348 }
349}
350
351bool Gralloc4Allocator::isLoaded() const {
352 return mAllocator != nullptr;
353}
354
355std::string Gralloc4Allocator::dumpDebugInfo() const {
356 std::string debugInfo;
357
358 mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
359
360 return debugInfo;
361}
362
363status_t Gralloc4Allocator::allocate(uint32_t width, uint32_t height, android::PixelFormat format,
364 uint32_t layerCount, uint64_t usage, uint32_t bufferCount,
365 uint32_t* outStride, buffer_handle_t* outBufferHandles) const {
366 IMapper::BufferDescriptorInfo descriptorInfo;
367 sBufferDescriptorInfo(width, height, format, layerCount, usage, &descriptorInfo);
368
369 BufferDescriptor descriptor;
370 status_t error = mMapper.createDescriptor(static_cast<void*>(&descriptorInfo),
371 static_cast<void*>(&descriptor));
372 if (error != NO_ERROR) {
373 return error;
374 }
375
376 auto ret = mAllocator->allocate(descriptor, bufferCount,
377 [&](const auto& tmpError, const auto& tmpStride,
378 const auto& tmpBuffers) {
379 error = static_cast<status_t>(tmpError);
380 if (tmpError != Error::NONE) {
381 return;
382 }
383
384 // import buffers
385 for (uint32_t i = 0; i < bufferCount; i++) {
386 error = mMapper.importBuffer(tmpBuffers[i],
387 &outBufferHandles[i]);
388 if (error != NO_ERROR) {
389 for (uint32_t j = 0; j < i; j++) {
390 mMapper.freeBuffer(outBufferHandles[j]);
391 outBufferHandles[j] = nullptr;
392 }
393 return;
394 }
395 }
396 *outStride = tmpStride;
397 });
398
399 // make sure the kernel driver sees BC_FREE_BUFFER and closes the fds now
400 hardware::IPCThreadState::self()->flushCommands();
401
402 return (ret.isOk()) ? error : static_cast<status_t>(kTransactionError);
403}
404
405} // namespace android