1 /*
2 * Copyright 2016 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 "Gralloc2"
18
19 #include <hidl/ServiceManagement.h>
20 #include <hwbinder/IPCThreadState.h>
21 #include <ui/Gralloc2.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
30 using android::hardware::graphics::allocator::V2_0::IAllocator;
31 using android::hardware::graphics::common::V1_1::BufferUsage;
32 using android::hardware::graphics::common::V1_1::PixelFormat;
33 using android::hardware::graphics::mapper::V2_0::BufferDescriptor;
34 using android::hardware::graphics::mapper::V2_0::Error;
35 using android::hardware::graphics::mapper::V2_0::YCbCrLayout;
36 using android::hardware::graphics::mapper::V2_1::IMapper;
37
38 namespace android {
39
40 namespace {
41
42 static constexpr Error kTransactionError = Error::NO_RESOURCES;
43
getValid10UsageBits()44 uint64_t getValid10UsageBits() {
45 static const uint64_t valid10UsageBits = []() -> uint64_t {
46 using hardware::graphics::common::V1_0::BufferUsage;
47 uint64_t bits = 0;
48 for (const auto bit : hardware::hidl_enum_range<BufferUsage>()) {
49 bits = bits | bit;
50 }
51 return bits;
52 }();
53 return valid10UsageBits;
54 }
55
getValid11UsageBits()56 uint64_t getValid11UsageBits() {
57 static const uint64_t valid11UsageBits = []() -> uint64_t {
58 using hardware::graphics::common::V1_1::BufferUsage;
59 uint64_t bits = 0;
60 for (const auto bit : hardware::hidl_enum_range<BufferUsage>()) {
61 bits = bits | bit;
62 }
63 return bits;
64 }();
65 return valid11UsageBits;
66 }
67
sGralloc2Rect(const Rect & rect)68 static inline IMapper::Rect sGralloc2Rect(const Rect& rect) {
69 IMapper::Rect outRect{};
70 outRect.left = rect.left;
71 outRect.top = rect.top;
72 outRect.width = rect.width();
73 outRect.height = rect.height();
74 return outRect;
75 }
76
77 } // anonymous namespace
78
preload()79 void Gralloc2Mapper::preload() {
80 android::hardware::preloadPassthroughService<hardware::graphics::mapper::V2_0::IMapper>();
81 }
82
Gralloc2Mapper()83 Gralloc2Mapper::Gralloc2Mapper() {
84 mMapper = hardware::graphics::mapper::V2_0::IMapper::getService();
85 if (mMapper == nullptr) {
86 ALOGW("mapper 2.x is not supported");
87 return;
88 }
89 if (mMapper->isRemote()) {
90 LOG_ALWAYS_FATAL("gralloc-mapper must be in passthrough mode");
91 }
92
93 // IMapper 2.1 is optional
94 mMapperV2_1 = IMapper::castFrom(mMapper);
95 }
96
isLoaded() const97 bool Gralloc2Mapper::isLoaded() const {
98 return mMapper != nullptr;
99 }
100
validateBufferDescriptorInfo(IMapper::BufferDescriptorInfo * descriptorInfo) const101 status_t Gralloc2Mapper::validateBufferDescriptorInfo(
102 IMapper::BufferDescriptorInfo* descriptorInfo) const {
103 uint64_t validUsageBits = getValid10UsageBits();
104 if (mMapperV2_1 != nullptr) {
105 validUsageBits = validUsageBits | getValid11UsageBits();
106 }
107
108 if (descriptorInfo->usage & ~validUsageBits) {
109 ALOGE("buffer descriptor contains invalid usage bits 0x%" PRIx64,
110 descriptorInfo->usage & ~validUsageBits);
111 return BAD_VALUE;
112 }
113
114 // Gralloc2 implementations never understand non-BLOB with GPU_DATA_BUFFER
115 // and do not reliably reject it.
116 if (descriptorInfo->usage & BufferUsage::GPU_DATA_BUFFER &&
117 descriptorInfo->format != hardware::graphics::common::V1_1::PixelFormat::BLOB) {
118 ALOGE("gralloc2 does not support non-BLOB pixel formats with GPU_DATA_BUFFER usage");
119 return BAD_VALUE;
120 }
121
122 return NO_ERROR;
123 }
124
createDescriptor(void * bufferDescriptorInfo,void * outBufferDescriptor) const125 status_t Gralloc2Mapper::createDescriptor(void* bufferDescriptorInfo,
126 void* outBufferDescriptor) const {
127 IMapper::BufferDescriptorInfo* descriptorInfo =
128 static_cast<IMapper::BufferDescriptorInfo*>(bufferDescriptorInfo);
129 BufferDescriptor* outDescriptor = static_cast<BufferDescriptor*>(outBufferDescriptor);
130
131 status_t status = validateBufferDescriptorInfo(descriptorInfo);
132 if (status != NO_ERROR) {
133 return status;
134 }
135
136 Error error;
137 auto hidl_cb = [&](const auto& tmpError, const auto& tmpDescriptor)
138 {
139 error = tmpError;
140 if (error != Error::NONE) {
141 return;
142 }
143
144 *outDescriptor = tmpDescriptor;
145 };
146
147 hardware::Return<void> ret;
148 if (mMapperV2_1 != nullptr) {
149 ret = mMapperV2_1->createDescriptor_2_1(*descriptorInfo, hidl_cb);
150 } else {
151 const hardware::graphics::mapper::V2_0::IMapper::BufferDescriptorInfo info = {
152 descriptorInfo->width,
153 descriptorInfo->height,
154 descriptorInfo->layerCount,
155 static_cast<hardware::graphics::common::V1_0::PixelFormat>(descriptorInfo->format),
156 descriptorInfo->usage,
157 };
158 ret = mMapper->createDescriptor(info, hidl_cb);
159 }
160
161 return static_cast<status_t>((ret.isOk()) ? error : kTransactionError);
162 }
163
importBuffer(const native_handle_t * rawHandle,buffer_handle_t * outBufferHandle) const164 status_t Gralloc2Mapper::importBuffer(const native_handle_t* rawHandle,
165 buffer_handle_t* outBufferHandle) const {
166 Error error;
167 auto ret = mMapper->importBuffer(rawHandle,
168 [&](const auto& tmpError, const auto& tmpBuffer)
169 {
170 error = tmpError;
171 if (error != Error::NONE) {
172 return;
173 }
174
175 *outBufferHandle = static_cast<buffer_handle_t>(tmpBuffer);
176 });
177
178 return static_cast<status_t>((ret.isOk()) ? error : kTransactionError);
179 }
180
freeBuffer(buffer_handle_t bufferHandle) const181 void Gralloc2Mapper::freeBuffer(buffer_handle_t bufferHandle) const {
182 auto buffer = const_cast<native_handle_t*>(bufferHandle);
183 auto ret = mMapper->freeBuffer(buffer);
184
185 auto error = (ret.isOk()) ? static_cast<Error>(ret) : kTransactionError;
186 ALOGE_IF(error != Error::NONE, "freeBuffer(%p) failed with %d",
187 buffer, error);
188 }
189
validateBufferSize(buffer_handle_t bufferHandle,uint32_t width,uint32_t height,android::PixelFormat format,uint32_t layerCount,uint64_t usage,uint32_t stride) const190 status_t Gralloc2Mapper::validateBufferSize(buffer_handle_t bufferHandle, uint32_t width,
191 uint32_t height, android::PixelFormat format,
192 uint32_t layerCount, uint64_t usage,
193 uint32_t stride) const {
194 if (mMapperV2_1 == nullptr) {
195 return NO_ERROR;
196 }
197
198 IMapper::BufferDescriptorInfo descriptorInfo = {};
199 descriptorInfo.width = width;
200 descriptorInfo.height = height;
201 descriptorInfo.layerCount = layerCount;
202 descriptorInfo.format = static_cast<hardware::graphics::common::V1_1::PixelFormat>(format);
203 descriptorInfo.usage = usage;
204
205 auto buffer = const_cast<native_handle_t*>(bufferHandle);
206 auto ret = mMapperV2_1->validateBufferSize(buffer, descriptorInfo, stride);
207
208 return static_cast<status_t>((ret.isOk()) ? static_cast<Error>(ret) : kTransactionError);
209 }
210
getTransportSize(buffer_handle_t bufferHandle,uint32_t * outNumFds,uint32_t * outNumInts) const211 void Gralloc2Mapper::getTransportSize(buffer_handle_t bufferHandle, uint32_t* outNumFds,
212 uint32_t* outNumInts) const {
213 *outNumFds = uint32_t(bufferHandle->numFds);
214 *outNumInts = uint32_t(bufferHandle->numInts);
215
216 if (mMapperV2_1 == nullptr) {
217 return;
218 }
219
220 Error error;
221 auto buffer = const_cast<native_handle_t*>(bufferHandle);
222 auto ret = mMapperV2_1->getTransportSize(buffer,
223 [&](const auto& tmpError, const auto& tmpNumFds, const auto& tmpNumInts) {
224 error = tmpError;
225 if (error != Error::NONE) {
226 return;
227 }
228
229 *outNumFds = tmpNumFds;
230 *outNumInts = tmpNumInts;
231 });
232
233 error = (ret.isOk()) ? error : kTransactionError;
234
235 ALOGE_IF(error != Error::NONE, "getTransportSize(%p) failed with %d", buffer, error);
236 }
237
lock(buffer_handle_t bufferHandle,uint64_t usage,const Rect & bounds,int acquireFence,void ** outData,int32_t * outBytesPerPixel,int32_t * outBytesPerStride) const238 status_t Gralloc2Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds,
239 int acquireFence, void** outData, int32_t* outBytesPerPixel,
240 int32_t* outBytesPerStride) const {
241 if (outBytesPerPixel) {
242 *outBytesPerPixel = -1;
243 }
244 if (outBytesPerStride) {
245 *outBytesPerStride = -1;
246 }
247 auto buffer = const_cast<native_handle_t*>(bufferHandle);
248
249 IMapper::Rect accessRegion = sGralloc2Rect(bounds);
250
251 // put acquireFence in a hidl_handle
252 hardware::hidl_handle acquireFenceHandle;
253 NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
254 if (acquireFence >= 0) {
255 auto h = native_handle_init(acquireFenceStorage, 1, 0);
256 h->data[0] = acquireFence;
257 acquireFenceHandle = h;
258 }
259
260 Error error;
261 auto ret = mMapper->lock(buffer, usage, accessRegion, acquireFenceHandle,
262 [&](const auto& tmpError, const auto& tmpData)
263 {
264 error = tmpError;
265 if (error != Error::NONE) {
266 return;
267 }
268
269 *outData = tmpData;
270 });
271
272 // we own acquireFence even on errors
273 if (acquireFence >= 0) {
274 close(acquireFence);
275 }
276
277 error = (ret.isOk()) ? error : kTransactionError;
278
279 ALOGW_IF(error != Error::NONE, "lock(%p, ...) failed: %d", bufferHandle, error);
280
281 return static_cast<status_t>(error);
282 }
283
lock(buffer_handle_t bufferHandle,uint64_t usage,const Rect & bounds,int acquireFence,android_ycbcr * ycbcr) const284 status_t Gralloc2Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds,
285 int acquireFence, android_ycbcr* ycbcr) const {
286 auto buffer = const_cast<native_handle_t*>(bufferHandle);
287
288 IMapper::Rect accessRegion = sGralloc2Rect(bounds);
289
290 // put acquireFence in a hidl_handle
291 hardware::hidl_handle acquireFenceHandle;
292 NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
293 if (acquireFence >= 0) {
294 auto h = native_handle_init(acquireFenceStorage, 1, 0);
295 h->data[0] = acquireFence;
296 acquireFenceHandle = h;
297 }
298
299 YCbCrLayout layout;
300 Error error;
301 auto ret = mMapper->lockYCbCr(buffer, usage, accessRegion,
302 acquireFenceHandle,
303 [&](const auto& tmpError, const auto& tmpLayout)
304 {
305 error = tmpError;
306 if (error != Error::NONE) {
307 return;
308 }
309
310 layout = tmpLayout;
311 });
312
313 if (error == Error::NONE) {
314 ycbcr->y = layout.y;
315 ycbcr->cb = layout.cb;
316 ycbcr->cr = layout.cr;
317 ycbcr->ystride = static_cast<size_t>(layout.yStride);
318 ycbcr->cstride = static_cast<size_t>(layout.cStride);
319 ycbcr->chroma_step = static_cast<size_t>(layout.chromaStep);
320 }
321
322 // we own acquireFence even on errors
323 if (acquireFence >= 0) {
324 close(acquireFence);
325 }
326
327 return static_cast<status_t>((ret.isOk()) ? error : kTransactionError);
328 }
329
unlock(buffer_handle_t bufferHandle) const330 int Gralloc2Mapper::unlock(buffer_handle_t bufferHandle) const {
331 auto buffer = const_cast<native_handle_t*>(bufferHandle);
332
333 int releaseFence = -1;
334 Error error;
335 auto ret = mMapper->unlock(buffer,
336 [&](const auto& tmpError, const auto& tmpReleaseFence)
337 {
338 error = tmpError;
339 if (error != Error::NONE) {
340 return;
341 }
342
343 auto fenceHandle = tmpReleaseFence.getNativeHandle();
344 if (fenceHandle && fenceHandle->numFds == 1) {
345 int fd = dup(fenceHandle->data[0]);
346 if (fd >= 0) {
347 releaseFence = fd;
348 } else {
349 ALOGD("failed to dup unlock release fence");
350 sync_wait(fenceHandle->data[0], -1);
351 }
352 }
353 });
354
355 error = (ret.isOk()) ? error : kTransactionError;
356 if (error != Error::NONE) {
357 ALOGE("unlock(%p) failed with %d", buffer, error);
358 }
359
360 return releaseFence;
361 }
362
Gralloc2Allocator(const Gralloc2Mapper & mapper)363 Gralloc2Allocator::Gralloc2Allocator(const Gralloc2Mapper& mapper) : mMapper(mapper) {
364 mAllocator = IAllocator::getService();
365 if (mAllocator == nullptr) {
366 ALOGW("allocator 2.x is not supported");
367 return;
368 }
369 }
370
isLoaded() const371 bool Gralloc2Allocator::isLoaded() const {
372 return mAllocator != nullptr;
373 }
374
dumpDebugInfo(bool) const375 std::string Gralloc2Allocator::dumpDebugInfo(bool /*less*/) const {
376 std::string debugInfo;
377
378 mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) {
379 debugInfo = tmpDebugInfo.c_str();
380 });
381
382 return debugInfo;
383 }
384
allocate(std::string,uint32_t width,uint32_t height,PixelFormat format,uint32_t layerCount,uint64_t usage,uint32_t * outStride,buffer_handle_t * outBufferHandles,bool importBuffers) const385 status_t Gralloc2Allocator::allocate(std::string /*requestorName*/, uint32_t width, uint32_t height,
386 PixelFormat format, uint32_t layerCount, uint64_t usage,
387 uint32_t* outStride, buffer_handle_t* outBufferHandles,
388 bool importBuffers) const {
389 IMapper::BufferDescriptorInfo descriptorInfo = {};
390 descriptorInfo.width = width;
391 descriptorInfo.height = height;
392 descriptorInfo.layerCount = layerCount;
393 descriptorInfo.format = static_cast<hardware::graphics::common::V1_1::PixelFormat>(format);
394 descriptorInfo.usage = usage;
395
396 BufferDescriptor descriptor;
397 status_t error = mMapper.createDescriptor(static_cast<void*>(&descriptorInfo),
398 static_cast<void*>(&descriptor));
399 if (error != NO_ERROR) {
400 return error;
401 }
402
403 constexpr auto bufferCount = 1;
404
405 auto ret = mAllocator->allocate(descriptor, bufferCount,
406 [&](const auto& tmpError, const auto& tmpStride,
407 const auto& tmpBuffers) {
408 error = static_cast<status_t>(tmpError);
409 if (tmpError != Error::NONE) {
410 return;
411 }
412
413 if (importBuffers) {
414 for (uint32_t i = 0; i < bufferCount; i++) {
415 error = mMapper.importBuffer(tmpBuffers[i],
416 &outBufferHandles[i]);
417 if (error != NO_ERROR) {
418 for (uint32_t j = 0; j < i; j++) {
419 mMapper.freeBuffer(outBufferHandles[j]);
420 outBufferHandles[j] = nullptr;
421 }
422 return;
423 }
424 }
425 } else {
426 for (uint32_t i = 0; i < bufferCount; i++) {
427 outBufferHandles[i] = native_handle_clone(
428 tmpBuffers[i].getNativeHandle());
429 if (!outBufferHandles[i]) {
430 for (uint32_t j = 0; j < i; j++) {
431 auto buffer = const_cast<native_handle_t*>(
432 outBufferHandles[j]);
433 native_handle_close(buffer);
434 native_handle_delete(buffer);
435 outBufferHandles[j] = nullptr;
436 }
437 }
438 }
439 }
440 *outStride = tmpStride;
441 });
442
443 // make sure the kernel driver sees BC_FREE_BUFFER and closes the fds now
444 hardware::IPCThreadState::self()->flushCommands();
445
446 return (ret.isOk()) ? error : static_cast<status_t>(kTransactionError);
447 }
448
449 } // namespace android
450