blob: 2ec6d18fda059f0c2cd5f6edbea6368ba0201949 [file] [log] [blame]
John Reck0ff95c92022-12-08 11:45:29 -05001/*
2 * Copyright (C) 2022 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 "Gralloc5"
18#define ATRACE_TAG ATRACE_TAG_GRAPHICS
19
20#include <ui/Gralloc5.h>
21
22#include <aidlcommonsupport/NativeHandle.h>
23#include <android/binder_manager.h>
24#include <android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h>
25#include <binder/IPCThreadState.h>
26#include <dlfcn.h>
27#include <ui/FatVector.h>
28#include <vndksupport/linker.h>
29
30using namespace aidl::android::hardware::graphics::allocator;
31using namespace aidl::android::hardware::graphics::common;
32using namespace ::android::hardware::graphics::mapper;
33
John Reckedcd8852023-07-25 16:03:44 -040034using ADataspace = aidl::android::hardware::graphics::common::Dataspace;
35using APixelFormat = aidl::android::hardware::graphics::common::PixelFormat;
36
John Reck0ff95c92022-12-08 11:45:29 -050037namespace android {
38
39static const auto kIAllocatorServiceName = IAllocator::descriptor + std::string("/default");
40static const auto kIAllocatorMinimumVersion = 2;
John Reckedcd8852023-07-25 16:03:44 -040041constexpr const char* kStandardMetadataName =
42 "android.hardware.graphics.common.StandardMetadataType";
John Reck0ff95c92022-12-08 11:45:29 -050043
44// TODO(b/72323293, b/72703005): Remove these invalid bits from callers
45static constexpr uint64_t kRemovedUsageBits = static_cast<uint64_t>((1 << 10) | (1 << 13));
46
47typedef AIMapper_Error (*AIMapper_loadIMapperFn)(AIMapper *_Nullable *_Nonnull outImplementation);
48
49struct Gralloc5 {
50 std::shared_ptr<IAllocator> allocator;
51 AIMapper *mapper = nullptr;
52};
53
54static std::shared_ptr<IAllocator> waitForAllocator() {
55 if (__builtin_available(android 31, *)) {
56 if (!AServiceManager_isDeclared(kIAllocatorServiceName.c_str())) {
57 return nullptr;
58 }
59 auto allocator = IAllocator::fromBinder(
60 ndk::SpAIBinder(AServiceManager_waitForService(kIAllocatorServiceName.c_str())));
61 if (!allocator) {
62 ALOGE("AIDL IAllocator declared but failed to get service");
63 return nullptr;
64 }
65
66 int32_t version = 0;
67 if (!allocator->getInterfaceVersion(&version).isOk()) {
68 ALOGE("Failed to query interface version");
69 return nullptr;
70 }
71 if (version < kIAllocatorMinimumVersion) {
72 return nullptr;
73 }
74 return allocator;
75 } else {
76 // TODO: LOG_ALWAYS_FATAL("libui is not backwards compatible");
77 return nullptr;
78 }
79}
80
81static void *loadIMapperLibrary() {
82 static void *imapperLibrary = []() -> void * {
83 auto allocator = waitForAllocator();
84 std::string mapperSuffix;
85 auto status = allocator->getIMapperLibrarySuffix(&mapperSuffix);
86 if (!status.isOk()) {
87 ALOGE("Failed to get IMapper library suffix");
88 return nullptr;
89 }
90
91 std::string lib_name = "mapper." + mapperSuffix + ".so";
92 void *so = android_load_sphal_library(lib_name.c_str(), RTLD_LOCAL | RTLD_NOW);
93 if (!so) {
94 ALOGE("Failed to load %s", lib_name.c_str());
95 }
96 return so;
97 }();
98 return imapperLibrary;
99}
100
101static const Gralloc5 &getInstance() {
102 static Gralloc5 instance = []() {
103 auto allocator = waitForAllocator();
104 if (!allocator) {
105 return Gralloc5{};
106 }
107 void *so = loadIMapperLibrary();
108 if (!so) {
109 return Gralloc5{};
110 }
111 auto loadIMapper = (AIMapper_loadIMapperFn)dlsym(so, "AIMapper_loadIMapper");
112 AIMapper *mapper = nullptr;
113 AIMapper_Error error = loadIMapper(&mapper);
114 if (error != AIMAPPER_ERROR_NONE) {
115 ALOGE("AIMapper_loadIMapper failed %d", error);
116 return Gralloc5{};
117 }
118 return Gralloc5{std::move(allocator), mapper};
119 }();
120 return instance;
121}
122
123template <StandardMetadataType T>
124static auto getStandardMetadata(AIMapper *mapper, buffer_handle_t bufferHandle)
125 -> decltype(StandardMetadata<T>::value::decode(nullptr, 0)) {
126 using Value = typename StandardMetadata<T>::value;
127 // TODO: Tune for common-case better
128 FatVector<uint8_t, 128> buffer;
129 int32_t sizeRequired = mapper->v5.getStandardMetadata(bufferHandle, static_cast<int64_t>(T),
130 buffer.data(), buffer.size());
131 if (sizeRequired < 0) {
132 ALOGW_IF(-AIMAPPER_ERROR_UNSUPPORTED != sizeRequired,
133 "Unexpected error %d from valid getStandardMetadata call", -sizeRequired);
134 return std::nullopt;
135 }
136 if ((size_t)sizeRequired > buffer.size()) {
137 buffer.resize(sizeRequired);
138 sizeRequired = mapper->v5.getStandardMetadata(bufferHandle, static_cast<int64_t>(T),
139 buffer.data(), buffer.size());
140 }
141 if (sizeRequired < 0 || (size_t)sizeRequired > buffer.size()) {
142 ALOGW("getStandardMetadata failed, received %d with buffer size %zd", sizeRequired,
143 buffer.size());
144 // Generate a fail type
145 return std::nullopt;
146 }
147 return Value::decode(buffer.data(), sizeRequired);
148}
149
150template <StandardMetadataType T>
151static AIMapper_Error setStandardMetadata(AIMapper *mapper, buffer_handle_t bufferHandle,
152 const typename StandardMetadata<T>::value_type &value) {
153 using Value = typename StandardMetadata<T>::value;
154 int32_t sizeRequired = Value::encode(value, nullptr, 0);
155 if (sizeRequired < 0) {
156 ALOGW("Failed to calculate required size");
157 return static_cast<AIMapper_Error>(-sizeRequired);
158 }
159 FatVector<uint8_t, 128> buffer;
160 buffer.resize(sizeRequired);
161 sizeRequired = Value::encode(value, buffer.data(), buffer.size());
162 if (sizeRequired < 0 || (size_t)sizeRequired > buffer.size()) {
163 ALOGW("Failed to encode with calculated size %d; buffer size %zd", sizeRequired,
164 buffer.size());
165 return static_cast<AIMapper_Error>(-sizeRequired);
166 }
167 return mapper->v5.setStandardMetadata(bufferHandle, static_cast<int64_t>(T), buffer.data(),
168 sizeRequired);
169}
170
171Gralloc5Allocator::Gralloc5Allocator(const Gralloc5Mapper &mapper) : mMapper(mapper) {
172 mAllocator = getInstance().allocator;
173}
174
175bool Gralloc5Allocator::isLoaded() const {
176 return mAllocator != nullptr;
177}
178
179static uint64_t getValidUsageBits() {
180 static const uint64_t validUsageBits = []() -> uint64_t {
181 uint64_t bits = 0;
182 for (const auto bit : ndk::enum_range<BufferUsage>{}) {
183 bits |= static_cast<int64_t>(bit);
184 }
185 return bits;
186 }();
187 return validUsageBits | kRemovedUsageBits;
188}
189
190static std::optional<BufferDescriptorInfo> makeDescriptor(std::string requestorName, uint32_t width,
191 uint32_t height, PixelFormat format,
192 uint32_t layerCount, uint64_t usage) {
193 uint64_t validUsageBits = getValidUsageBits();
194 if (usage & ~validUsageBits) {
195 ALOGE("buffer descriptor contains invalid usage bits 0x%" PRIx64, usage & ~validUsageBits);
196 return std::nullopt;
197 }
198
199 BufferDescriptorInfo descriptorInfo{
200 .width = static_cast<int32_t>(width),
201 .height = static_cast<int32_t>(height),
202 .layerCount = static_cast<int32_t>(layerCount),
203 .format = static_cast<::aidl::android::hardware::graphics::common::PixelFormat>(format),
204 .usage = static_cast<BufferUsage>(usage),
205 };
206 auto nameLength = std::min(requestorName.length(), descriptorInfo.name.size() - 1);
207 memcpy(descriptorInfo.name.data(), requestorName.data(), nameLength);
208 requestorName.data()[nameLength] = 0;
209 return descriptorInfo;
210}
211
212std::string Gralloc5Allocator::dumpDebugInfo(bool less) const {
213 return mMapper.dumpBuffers(less);
214}
215
216status_t Gralloc5Allocator::allocate(std::string requestorName, uint32_t width, uint32_t height,
217 android::PixelFormat format, uint32_t layerCount,
218 uint64_t usage, uint32_t bufferCount, uint32_t *outStride,
219 buffer_handle_t *outBufferHandles, bool importBuffers) const {
220 auto descriptorInfo = makeDescriptor(requestorName, width, height, format, layerCount, usage);
221 if (!descriptorInfo) {
222 return BAD_VALUE;
223 }
224
225 AllocationResult result;
226 auto status = mAllocator->allocate2(*descriptorInfo, bufferCount, &result);
227 if (!status.isOk()) {
228 auto error = status.getExceptionCode();
229 if (error == EX_SERVICE_SPECIFIC) {
230 error = status.getServiceSpecificError();
231 }
232 if (error == OK) {
233 error = UNKNOWN_ERROR;
234 }
235 return error;
236 }
237
238 if (importBuffers) {
239 for (uint32_t i = 0; i < bufferCount; i++) {
240 auto handle = makeFromAidl(result.buffers[i]);
241 auto error = mMapper.importBuffer(handle, &outBufferHandles[i]);
242 native_handle_delete(handle);
243 if (error != NO_ERROR) {
244 for (uint32_t j = 0; j < i; j++) {
245 mMapper.freeBuffer(outBufferHandles[j]);
246 outBufferHandles[j] = nullptr;
247 }
248 return error;
249 }
250 }
251 } else {
252 for (uint32_t i = 0; i < bufferCount; i++) {
253 outBufferHandles[i] = dupFromAidl(result.buffers[i]);
254 if (!outBufferHandles[i]) {
255 for (uint32_t j = 0; j < i; j++) {
256 auto buffer = const_cast<native_handle_t *>(outBufferHandles[j]);
257 native_handle_close(buffer);
258 native_handle_delete(buffer);
259 outBufferHandles[j] = nullptr;
260 }
261 return NO_MEMORY;
262 }
263 }
264 }
265
266 *outStride = result.stride;
267
268 // Release all the resources held by AllocationResult (specifically any remaining FDs)
269 result = {};
270 // make sure the kernel driver sees BC_FREE_BUFFER and closes the fds now
271 // TODO: Re-enable this at some point if it's necessary. We can't do it now because libui
272 // is marked apex_available (b/214400477) and libbinder isn't (which of course is correct)
273 // IPCThreadState::self()->flushCommands();
274
275 return OK;
276}
277
278void Gralloc5Mapper::preload() {
279 // TODO(b/261858155): Implement. We can't bounce off of IAllocator for this because zygote can't
280 // use binder. So when an alternate strategy of retrieving the library prefix is available,
281 // use that here.
282}
283
284Gralloc5Mapper::Gralloc5Mapper() {
285 mMapper = getInstance().mapper;
286}
287
288bool Gralloc5Mapper::isLoaded() const {
289 return mMapper != nullptr && mMapper->version >= AIMAPPER_VERSION_5;
290}
291
John Reckedcd8852023-07-25 16:03:44 -0400292static bool isStandardMetadata(AIMapper_MetadataType metadataType) {
293 return strcmp(kStandardMetadataName, metadataType.name) == 0;
294}
295
296struct DumpBufferResult {
297 uint64_t bufferId;
298 std::string name;
299 uint64_t width;
300 uint64_t height;
301 uint64_t layerCount;
302 APixelFormat pixelFormatRequested;
303 uint32_t pixelFormatFourCC;
304 uint64_t pixelFormatModifier;
305 BufferUsage usage;
306 ADataspace dataspace;
307 uint64_t allocationSize;
308 uint64_t protectedContent;
309 ExtendableType compression;
310 ExtendableType interlaced;
311 ExtendableType chromaSiting;
312 std::vector<ui::PlaneLayout> planeLayouts;
313};
314
315#define DECODE_TO(name, output) \
316 case StandardMetadataType::name: \
317 output = StandardMetadata<StandardMetadataType::name>::value ::decode(value, valueSize) \
318 .value(); \
319 break
320
321static void dumpBufferCommon(DumpBufferResult* outResult, AIMapper_MetadataType metadataType,
322 const void* value, size_t valueSize) {
323 if (!isStandardMetadata(metadataType)) {
324 return;
325 }
326 StandardMetadataType type = (StandardMetadataType)metadataType.value;
327 switch (type) {
328 DECODE_TO(BUFFER_ID, outResult->bufferId);
329 DECODE_TO(NAME, outResult->name);
330 DECODE_TO(WIDTH, outResult->width);
331 DECODE_TO(HEIGHT, outResult->height);
332 DECODE_TO(LAYER_COUNT, outResult->layerCount);
333 DECODE_TO(PIXEL_FORMAT_REQUESTED, outResult->pixelFormatRequested);
334 DECODE_TO(PIXEL_FORMAT_FOURCC, outResult->pixelFormatFourCC);
335 DECODE_TO(PIXEL_FORMAT_MODIFIER, outResult->pixelFormatModifier);
336 DECODE_TO(USAGE, outResult->usage);
337 DECODE_TO(DATASPACE, outResult->dataspace);
338 DECODE_TO(ALLOCATION_SIZE, outResult->allocationSize);
339 DECODE_TO(PROTECTED_CONTENT, outResult->protectedContent);
340 DECODE_TO(COMPRESSION, outResult->compression);
341 DECODE_TO(INTERLACED, outResult->interlaced);
342 DECODE_TO(CHROMA_SITING, outResult->chromaSiting);
343 DECODE_TO(PLANE_LAYOUTS, outResult->planeLayouts);
344 default:
345 break;
346 }
347}
348
349#undef DECODE_TO
350
351template <typename EnumT, typename = std::enable_if_t<std::is_enum<EnumT>{}>>
352constexpr std::underlying_type_t<EnumT> to_underlying(EnumT e) noexcept {
353 return static_cast<std::underlying_type_t<EnumT>>(e);
354}
355
356static void writeDumpToStream(const DumpBufferResult& bufferDump, std::ostream& outDump,
357 bool less) {
358 double allocationSizeKiB = static_cast<double>(bufferDump.allocationSize) / 1024;
359
360 outDump << "+ name:" << bufferDump.name << ", id:" << bufferDump.bufferId
361 << ", size:" << std::fixed << allocationSizeKiB << "KiB, w/h:" << bufferDump.width
362 << "x" << bufferDump.height << ", usage: 0x" << std::hex
363 << to_underlying(bufferDump.usage) << std::dec
364 << ", req fmt:" << to_underlying(bufferDump.pixelFormatRequested)
365 << ", fourcc/mod:" << bufferDump.pixelFormatFourCC << "/"
366 << bufferDump.pixelFormatModifier << ", dataspace: 0x" << std::hex
367 << to_underlying(bufferDump.dataspace) << std::dec << ", compressed: ";
368
369 if (less) {
370 bool isCompressed = !gralloc4::isStandardCompression(bufferDump.compression) ||
371 (gralloc4::getStandardCompressionValue(bufferDump.compression) !=
372 ui::Compression::NONE);
373 outDump << std::boolalpha << isCompressed << "\n";
374 } else {
375 outDump << gralloc4::getCompressionName(bufferDump.compression) << "\n";
376 }
377
378 if (!less) {
379 bool firstPlane = true;
380 for (const auto& planeLayout : bufferDump.planeLayouts) {
381 if (firstPlane) {
382 firstPlane = false;
383 outDump << "\tplanes: ";
384 } else {
385 outDump << "\t ";
386 }
387
388 for (size_t i = 0; i < planeLayout.components.size(); i++) {
389 const auto& planeLayoutComponent = planeLayout.components[i];
390 outDump << gralloc4::getPlaneLayoutComponentTypeName(planeLayoutComponent.type);
391 if (i < planeLayout.components.size() - 1) {
392 outDump << "/";
393 } else {
394 outDump << ":\t";
395 }
396 }
397 outDump << " w/h:" << planeLayout.widthInSamples << "x" << planeLayout.heightInSamples
398 << ", stride:" << planeLayout.strideInBytes
399 << " bytes, size:" << planeLayout.totalSizeInBytes;
400 outDump << ", inc:" << planeLayout.sampleIncrementInBits
401 << " bits, subsampling w/h:" << planeLayout.horizontalSubsampling << "x"
402 << planeLayout.verticalSubsampling;
403 outDump << "\n";
404 }
405
406 outDump << "\tlayer cnt: " << bufferDump.layerCount
407 << ", protected content: " << bufferDump.protectedContent
408 << ", interlaced: " << gralloc4::getInterlacedName(bufferDump.interlaced)
409 << ", chroma siting:" << gralloc4::getChromaSitingName(bufferDump.chromaSiting)
410 << "\n";
411 }
412}
413
John Reck0ff95c92022-12-08 11:45:29 -0500414std::string Gralloc5Mapper::dumpBuffer(buffer_handle_t bufferHandle, bool less) const {
John Reckedcd8852023-07-25 16:03:44 -0400415 DumpBufferResult bufferInfo;
416 AIMapper_DumpBufferCallback dumpBuffer = [](void* contextPtr,
417 AIMapper_MetadataType metadataType,
418 const void* _Nonnull value, size_t valueSize) {
419 DumpBufferResult* context = reinterpret_cast<DumpBufferResult*>(contextPtr);
420 dumpBufferCommon(context, metadataType, value, valueSize);
421 };
422 AIMapper_Error error = mMapper->v5.dumpBuffer(bufferHandle, dumpBuffer, &bufferInfo);
423 if (error != AIMAPPER_ERROR_NONE) {
424 ALOGE("Error dumping buffer: %d", error);
425 return std::string{};
426 }
427 std::ostringstream stream;
428 stream.precision(2);
429 writeDumpToStream(bufferInfo, stream, less);
430 return stream.str();
John Reck0ff95c92022-12-08 11:45:29 -0500431}
432
433std::string Gralloc5Mapper::dumpBuffers(bool less) const {
John Reckedcd8852023-07-25 16:03:44 -0400434 class DumpAllBuffersContext {
435 private:
436 bool mHasPending = false;
437 DumpBufferResult mPending;
438 std::vector<DumpBufferResult> mResults;
439
440 public:
441 DumpAllBuffersContext() { mResults.reserve(10); }
442
443 void commit() {
444 if (mHasPending) {
445 mResults.push_back(mPending);
446 mHasPending = false;
447 }
448 }
449
450 DumpBufferResult* write() {
451 mHasPending = true;
452 return &mPending;
453 }
454
455 const std::vector<DumpBufferResult>& results() {
456 commit();
457 return mResults;
458 }
459 } context;
460
461 AIMapper_BeginDumpBufferCallback beginCallback = [](void* contextPtr) {
462 DumpAllBuffersContext* context = reinterpret_cast<DumpAllBuffersContext*>(contextPtr);
463 context->commit();
464 };
465
466 AIMapper_DumpBufferCallback dumpBuffer = [](void* contextPtr,
467 AIMapper_MetadataType metadataType,
468 const void* _Nonnull value, size_t valueSize) {
469 DumpAllBuffersContext* context = reinterpret_cast<DumpAllBuffersContext*>(contextPtr);
470 dumpBufferCommon(context->write(), metadataType, value, valueSize);
471 };
472
473 AIMapper_Error error = mMapper->v5.dumpAllBuffers(beginCallback, dumpBuffer, &context);
474 if (error != AIMAPPER_ERROR_NONE) {
475 ALOGE("Error dumping buffers: %d", error);
476 return std::string{};
477 }
478 uint64_t totalAllocationSize = 0;
479 std::ostringstream stream;
480 stream.precision(2);
481 stream << "Imported gralloc buffers:\n";
482
483 for (const auto& bufferDump : context.results()) {
484 writeDumpToStream(bufferDump, stream, less);
485 totalAllocationSize += bufferDump.allocationSize;
486 }
487
488 double totalAllocationSizeKiB = static_cast<double>(totalAllocationSize) / 1024;
489 stream << "Total imported by gralloc: " << totalAllocationSizeKiB << "KiB\n";
490 return stream.str();
John Reck0ff95c92022-12-08 11:45:29 -0500491}
492
493status_t Gralloc5Mapper::importBuffer(const native_handle_t *rawHandle,
494 buffer_handle_t *outBufferHandle) const {
495 return mMapper->v5.importBuffer(rawHandle, outBufferHandle);
496}
497
498void Gralloc5Mapper::freeBuffer(buffer_handle_t bufferHandle) const {
499 mMapper->v5.freeBuffer(bufferHandle);
500}
501
502status_t Gralloc5Mapper::validateBufferSize(buffer_handle_t bufferHandle, uint32_t width,
503 uint32_t height, PixelFormat format,
504 uint32_t layerCount, uint64_t usage,
505 uint32_t stride) const {
506 {
507 auto value = getStandardMetadata<StandardMetadataType::WIDTH>(mMapper, bufferHandle);
508 if (width != value) {
509 ALOGW("Width didn't match, expected %d got %" PRId64, width, value.value_or(-1));
510 return BAD_VALUE;
511 }
512 }
513 {
514 auto value = getStandardMetadata<StandardMetadataType::HEIGHT>(mMapper, bufferHandle);
515 if (height != value) {
516 ALOGW("Height didn't match, expected %d got %" PRId64, height, value.value_or(-1));
517 return BAD_VALUE;
518 }
519 }
520 {
John Reck54a98142023-11-21 11:13:40 -0500521 auto expected = static_cast<APixelFormat>(format);
522 if (expected != APixelFormat::IMPLEMENTATION_DEFINED) {
523 auto value =
524 getStandardMetadata<StandardMetadataType::PIXEL_FORMAT_REQUESTED>(mMapper,
525 bufferHandle);
526 if (expected != value) {
527 ALOGW("Format didn't match, expected %d got %s", format,
528 value.has_value() ? toString(*value).c_str() : "<null>");
529 return BAD_VALUE;
530 }
John Reck0ff95c92022-12-08 11:45:29 -0500531 }
532 }
533 {
534 auto value = getStandardMetadata<StandardMetadataType::LAYER_COUNT>(mMapper, bufferHandle);
535 if (layerCount != value) {
536 ALOGW("Layer count didn't match, expected %d got %" PRId64, layerCount,
537 value.value_or(-1));
538 return BAD_VALUE;
539 }
540 }
John Reck47390ec2023-05-24 13:46:37 -0400541 // TODO: This can false-positive fail if the allocator adjusted the USAGE bits internally
542 // Investigate further & re-enable or remove, but for now ignoring usage should be OK
543 (void)usage;
544 // {
545 // auto value = getStandardMetadata<StandardMetadataType::USAGE>(mMapper, bufferHandle);
546 // if (static_cast<BufferUsage>(usage) != value) {
547 // ALOGW("Usage didn't match, expected %" PRIu64 " got %" PRId64, usage,
548 // static_cast<int64_t>(value.value_or(BufferUsage::CPU_READ_NEVER)));
549 // return BAD_VALUE;
550 // }
551 // }
John Reck0ff95c92022-12-08 11:45:29 -0500552 {
John Recke225b282023-03-24 16:15:17 -0400553 auto value = getStandardMetadata<StandardMetadataType::STRIDE>(mMapper, bufferHandle);
554 if (stride != value) {
555 ALOGW("Stride didn't match, expected %" PRIu32 " got %" PRId32, stride,
556 value.value_or(-1));
557 return BAD_VALUE;
558 }
John Reck0ff95c92022-12-08 11:45:29 -0500559 }
560 return OK;
561}
562
563void Gralloc5Mapper::getTransportSize(buffer_handle_t bufferHandle, uint32_t *outNumFds,
564 uint32_t *outNumInts) const {
565 mMapper->v5.getTransportSize(bufferHandle, outNumFds, outNumInts);
566}
567
568status_t Gralloc5Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect &bounds,
569 int acquireFence, void **outData, int32_t *outBytesPerPixel,
570 int32_t *outBytesPerStride) const {
571 std::vector<ui::PlaneLayout> planeLayouts;
572 status_t err = getPlaneLayouts(bufferHandle, &planeLayouts);
573
574 if (err == NO_ERROR && !planeLayouts.empty()) {
575 if (outBytesPerPixel) {
576 int32_t bitsPerPixel = planeLayouts.front().sampleIncrementInBits;
577 for (const auto &planeLayout : planeLayouts) {
578 if (bitsPerPixel != planeLayout.sampleIncrementInBits) {
579 bitsPerPixel = -1;
580 }
581 }
582 if (bitsPerPixel >= 0 && bitsPerPixel % 8 == 0) {
583 *outBytesPerPixel = bitsPerPixel / 8;
584 } else {
585 *outBytesPerPixel = -1;
586 }
587 }
588 if (outBytesPerStride) {
589 int32_t bytesPerStride = planeLayouts.front().strideInBytes;
590 for (const auto &planeLayout : planeLayouts) {
591 if (bytesPerStride != planeLayout.strideInBytes) {
592 bytesPerStride = -1;
593 }
594 }
595 if (bytesPerStride >= 0) {
596 *outBytesPerStride = bytesPerStride;
597 } else {
598 *outBytesPerStride = -1;
599 }
600 }
601 }
602
603 auto status = mMapper->v5.lock(bufferHandle, usage, bounds, acquireFence, outData);
604
605 ALOGW_IF(status != AIMAPPER_ERROR_NONE, "lock(%p, ...) failed: %d", bufferHandle, status);
606 return static_cast<status_t>(status);
607}
608
609status_t Gralloc5Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect &bounds,
610 int acquireFence, android_ycbcr *outYcbcr) const {
611 if (!outYcbcr) {
612 return BAD_VALUE;
613 }
614
615 // TODO(b/262279301): Change the return type of ::unlock to unique_fd instead of int so that
616 // ignoring the return value "just works" instead
617 auto unlock = [this](buffer_handle_t bufferHandle) {
618 int fence = this->unlock(bufferHandle);
619 if (fence != -1) {
620 ::close(fence);
621 }
622 };
623
624 std::vector<ui::PlaneLayout> planeLayouts;
625 status_t error = getPlaneLayouts(bufferHandle, &planeLayouts);
626 if (error != NO_ERROR) {
627 return error;
628 }
629
630 void *data = nullptr;
631 error = lock(bufferHandle, usage, bounds, acquireFence, &data, nullptr, nullptr);
632 if (error != NO_ERROR) {
633 return error;
634 }
635
636 android_ycbcr ycbcr;
637
638 ycbcr.y = nullptr;
639 ycbcr.cb = nullptr;
640 ycbcr.cr = nullptr;
641 ycbcr.ystride = 0;
642 ycbcr.cstride = 0;
643 ycbcr.chroma_step = 0;
644
645 for (const auto &planeLayout : planeLayouts) {
646 for (const auto &planeLayoutComponent : planeLayout.components) {
647 if (!gralloc4::isStandardPlaneLayoutComponentType(planeLayoutComponent.type)) {
648 continue;
649 }
650
651 uint8_t *tmpData = static_cast<uint8_t *>(data) + planeLayout.offsetInBytes;
652
653 // Note that `offsetInBits` may not be a multiple of 8 for packed formats (e.g. P010)
654 // but we still want to point to the start of the first byte.
655 tmpData += (planeLayoutComponent.offsetInBits / 8);
656
657 uint64_t sampleIncrementInBytes;
658
659 auto type = static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value);
660 switch (type) {
661 case PlaneLayoutComponentType::Y:
662 if ((ycbcr.y != nullptr) || (planeLayout.sampleIncrementInBits % 8 != 0)) {
663 unlock(bufferHandle);
664 return BAD_VALUE;
665 }
666 ycbcr.y = tmpData;
667 ycbcr.ystride = planeLayout.strideInBytes;
668 break;
669
670 case PlaneLayoutComponentType::CB:
671 case PlaneLayoutComponentType::CR:
672 if (planeLayout.sampleIncrementInBits % 8 != 0) {
673 unlock(bufferHandle);
674 return BAD_VALUE;
675 }
676
677 sampleIncrementInBytes = planeLayout.sampleIncrementInBits / 8;
678 if ((sampleIncrementInBytes != 1) && (sampleIncrementInBytes != 2) &&
679 (sampleIncrementInBytes != 4)) {
680 unlock(bufferHandle);
681 return BAD_VALUE;
682 }
683
684 if (ycbcr.cstride == 0 && ycbcr.chroma_step == 0) {
685 ycbcr.cstride = planeLayout.strideInBytes;
686 ycbcr.chroma_step = sampleIncrementInBytes;
687 } else {
688 if ((static_cast<int64_t>(ycbcr.cstride) != planeLayout.strideInBytes) ||
689 (ycbcr.chroma_step != sampleIncrementInBytes)) {
690 unlock(bufferHandle);
691 return BAD_VALUE;
692 }
693 }
694
695 if (type == PlaneLayoutComponentType::CB) {
696 if (ycbcr.cb != nullptr) {
697 unlock(bufferHandle);
698 return BAD_VALUE;
699 }
700 ycbcr.cb = tmpData;
701 } else {
702 if (ycbcr.cr != nullptr) {
703 unlock(bufferHandle);
704 return BAD_VALUE;
705 }
706 ycbcr.cr = tmpData;
707 }
708 break;
709 default:
710 break;
711 };
712 }
713 }
714
715 *outYcbcr = ycbcr;
716 return OK;
717}
718
719int Gralloc5Mapper::unlock(buffer_handle_t bufferHandle) const {
720 int fence = -1;
721 AIMapper_Error error = mMapper->v5.unlock(bufferHandle, &fence);
722 if (error != AIMAPPER_ERROR_NONE) {
723 ALOGW("unlock failed with error %d", error);
724 }
725 return fence;
726}
727
728status_t Gralloc5Mapper::isSupported(uint32_t width, uint32_t height, PixelFormat format,
729 uint32_t layerCount, uint64_t usage,
730 bool *outSupported) const {
731 auto descriptorInfo = makeDescriptor("", width, height, format, layerCount, usage);
732 if (!descriptorInfo) {
733 *outSupported = false;
734 return OK;
735 }
736 auto status = getInstance().allocator->isSupported(*descriptorInfo, outSupported);
737 if (!status.isOk()) {
738 ALOGW("IAllocator::isSupported error %d (%s)", status.getStatus(), status.getMessage());
739 *outSupported = false;
740 }
741 return OK;
742}
743
744status_t Gralloc5Mapper::getBufferId(buffer_handle_t bufferHandle, uint64_t *outBufferId) const {
745 auto value = getStandardMetadata<StandardMetadataType::BUFFER_ID>(mMapper, bufferHandle);
746 if (value.has_value()) {
747 *outBufferId = *value;
748 return OK;
749 }
750 return UNKNOWN_TRANSACTION;
751}
752
753status_t Gralloc5Mapper::getName(buffer_handle_t bufferHandle, std::string *outName) const {
754 auto value = getStandardMetadata<StandardMetadataType::NAME>(mMapper, bufferHandle);
755 if (value.has_value()) {
756 *outName = *value;
757 return OK;
758 }
759 return UNKNOWN_TRANSACTION;
760}
761
762status_t Gralloc5Mapper::getWidth(buffer_handle_t bufferHandle, uint64_t *outWidth) const {
763 auto value = getStandardMetadata<StandardMetadataType::WIDTH>(mMapper, bufferHandle);
764 if (value.has_value()) {
765 *outWidth = *value;
766 return OK;
767 }
768 return UNKNOWN_TRANSACTION;
769}
770
771status_t Gralloc5Mapper::getHeight(buffer_handle_t bufferHandle, uint64_t *outHeight) const {
772 auto value = getStandardMetadata<StandardMetadataType::HEIGHT>(mMapper, bufferHandle);
773 if (value.has_value()) {
774 *outHeight = *value;
775 return OK;
776 }
777 return UNKNOWN_TRANSACTION;
778}
779
780status_t Gralloc5Mapper::getLayerCount(buffer_handle_t bufferHandle,
781 uint64_t *outLayerCount) const {
782 auto value = getStandardMetadata<StandardMetadataType::LAYER_COUNT>(mMapper, bufferHandle);
783 if (value.has_value()) {
784 *outLayerCount = *value;
785 return OK;
786 }
787 return UNKNOWN_TRANSACTION;
788}
789
790status_t Gralloc5Mapper::getPixelFormatRequested(buffer_handle_t bufferHandle,
791 ui::PixelFormat *outPixelFormatRequested) const {
792 auto value = getStandardMetadata<StandardMetadataType::PIXEL_FORMAT_REQUESTED>(mMapper,
793 bufferHandle);
794 if (value.has_value()) {
795 *outPixelFormatRequested = static_cast<ui::PixelFormat>(*value);
796 return OK;
797 }
798 return UNKNOWN_TRANSACTION;
799}
800
801status_t Gralloc5Mapper::getPixelFormatFourCC(buffer_handle_t bufferHandle,
802 uint32_t *outPixelFormatFourCC) const {
803 auto value =
804 getStandardMetadata<StandardMetadataType::PIXEL_FORMAT_FOURCC>(mMapper, bufferHandle);
805 if (value.has_value()) {
806 *outPixelFormatFourCC = *value;
807 return OK;
808 }
809 return UNKNOWN_TRANSACTION;
810}
811
812status_t Gralloc5Mapper::getPixelFormatModifier(buffer_handle_t bufferHandle,
813 uint64_t *outPixelFormatModifier) const {
814 auto value =
815 getStandardMetadata<StandardMetadataType::PIXEL_FORMAT_MODIFIER>(mMapper, bufferHandle);
816 if (value.has_value()) {
817 *outPixelFormatModifier = *value;
818 return OK;
819 }
820 return UNKNOWN_TRANSACTION;
821}
822
823status_t Gralloc5Mapper::getUsage(buffer_handle_t bufferHandle, uint64_t *outUsage) const {
824 auto value = getStandardMetadata<StandardMetadataType::USAGE>(mMapper, bufferHandle);
825 if (value.has_value()) {
826 *outUsage = static_cast<uint64_t>(*value);
827 return OK;
828 }
829 return UNKNOWN_TRANSACTION;
830}
831
832status_t Gralloc5Mapper::getAllocationSize(buffer_handle_t bufferHandle,
833 uint64_t *outAllocationSize) const {
834 auto value = getStandardMetadata<StandardMetadataType::ALLOCATION_SIZE>(mMapper, bufferHandle);
835 if (value.has_value()) {
836 *outAllocationSize = *value;
837 return OK;
838 }
839 return UNKNOWN_TRANSACTION;
840}
841
842status_t Gralloc5Mapper::getProtectedContent(buffer_handle_t bufferHandle,
843 uint64_t *outProtectedContent) const {
844 auto value =
845 getStandardMetadata<StandardMetadataType::PROTECTED_CONTENT>(mMapper, bufferHandle);
846 if (value.has_value()) {
847 *outProtectedContent = *value;
848 return OK;
849 }
850 return UNKNOWN_TRANSACTION;
851}
852
853status_t Gralloc5Mapper::getCompression(
854 buffer_handle_t bufferHandle,
855 aidl::android::hardware::graphics::common::ExtendableType *outCompression) const {
856 auto value = getStandardMetadata<StandardMetadataType::COMPRESSION>(mMapper, bufferHandle);
857 if (value.has_value()) {
858 *outCompression = *value;
859 return OK;
860 }
861 return UNKNOWN_TRANSACTION;
862}
863
864status_t Gralloc5Mapper::getCompression(buffer_handle_t bufferHandle,
865 ui::Compression *outCompression) const {
866 auto value = getStandardMetadata<StandardMetadataType::COMPRESSION>(mMapper, bufferHandle);
867 if (!value.has_value()) {
868 return UNKNOWN_TRANSACTION;
869 }
870 if (!gralloc4::isStandardCompression(*value)) {
871 return BAD_TYPE;
872 }
873 *outCompression = gralloc4::getStandardCompressionValue(*value);
874 return OK;
875}
876
877status_t Gralloc5Mapper::getInterlaced(
878 buffer_handle_t bufferHandle,
879 aidl::android::hardware::graphics::common::ExtendableType *outInterlaced) const {
880 auto value = getStandardMetadata<StandardMetadataType::INTERLACED>(mMapper, bufferHandle);
881 if (value.has_value()) {
882 *outInterlaced = *value;
883 return OK;
884 }
885 return UNKNOWN_TRANSACTION;
886}
887
888status_t Gralloc5Mapper::getInterlaced(buffer_handle_t bufferHandle,
889 ui::Interlaced *outInterlaced) const {
890 if (!outInterlaced) {
891 return BAD_VALUE;
892 }
893 ExtendableType interlaced;
894 status_t error = getInterlaced(bufferHandle, &interlaced);
895 if (error) {
896 return error;
897 }
898 if (!gralloc4::isStandardInterlaced(interlaced)) {
899 return BAD_TYPE;
900 }
901 *outInterlaced = gralloc4::getStandardInterlacedValue(interlaced);
902 return NO_ERROR;
903}
904
905status_t Gralloc5Mapper::getChromaSiting(
906 buffer_handle_t bufferHandle,
907 aidl::android::hardware::graphics::common::ExtendableType *outChromaSiting) const {
908 auto value = getStandardMetadata<StandardMetadataType::CHROMA_SITING>(mMapper, bufferHandle);
909 if (value.has_value()) {
910 *outChromaSiting = *value;
911 return OK;
912 }
913 return UNKNOWN_TRANSACTION;
914}
915
916status_t Gralloc5Mapper::getChromaSiting(buffer_handle_t bufferHandle,
917 ui::ChromaSiting *outChromaSiting) const {
918 if (!outChromaSiting) {
919 return BAD_VALUE;
920 }
921 ExtendableType chromaSiting;
922 status_t error = getChromaSiting(bufferHandle, &chromaSiting);
923 if (error) {
924 return error;
925 }
926 if (!gralloc4::isStandardChromaSiting(chromaSiting)) {
927 return BAD_TYPE;
928 }
929 *outChromaSiting = gralloc4::getStandardChromaSitingValue(chromaSiting);
930 return NO_ERROR;
931}
932
933status_t Gralloc5Mapper::getPlaneLayouts(buffer_handle_t bufferHandle,
934 std::vector<ui::PlaneLayout> *outPlaneLayouts) const {
935 auto value = getStandardMetadata<StandardMetadataType::PLANE_LAYOUTS>(mMapper, bufferHandle);
936 if (value.has_value()) {
937 *outPlaneLayouts = *value;
938 return OK;
939 }
940 return UNKNOWN_TRANSACTION;
941}
942
943status_t Gralloc5Mapper::getDataspace(buffer_handle_t bufferHandle,
944 ui::Dataspace *outDataspace) const {
945 auto value = getStandardMetadata<StandardMetadataType::DATASPACE>(mMapper, bufferHandle);
946 if (value.has_value()) {
947 *outDataspace = static_cast<ui::Dataspace>(*value);
948 return OK;
949 }
950 return UNKNOWN_TRANSACTION;
951}
952
953status_t Gralloc5Mapper::setDataspace(buffer_handle_t bufferHandle, ui::Dataspace dataspace) const {
954 return setStandardMetadata<StandardMetadataType::DATASPACE>(mMapper, bufferHandle,
955 static_cast<Dataspace>(dataspace));
956}
957
958status_t Gralloc5Mapper::getBlendMode(buffer_handle_t bufferHandle,
959 ui::BlendMode *outBlendMode) const {
960 auto value = getStandardMetadata<StandardMetadataType::BLEND_MODE>(mMapper, bufferHandle);
961 if (value.has_value()) {
962 *outBlendMode = static_cast<ui::BlendMode>(*value);
963 return OK;
964 }
965 return UNKNOWN_TRANSACTION;
966}
967
968status_t Gralloc5Mapper::getSmpte2086(buffer_handle_t bufferHandle,
969 std::optional<ui::Smpte2086> *outSmpte2086) const {
970 auto value = getStandardMetadata<StandardMetadataType::SMPTE2086>(mMapper, bufferHandle);
971 if (value.has_value()) {
972 *outSmpte2086 = *value;
973 return OK;
974 }
975 return UNKNOWN_TRANSACTION;
976}
977
978status_t Gralloc5Mapper::setSmpte2086(buffer_handle_t bufferHandle,
979 std::optional<ui::Smpte2086> smpte2086) const {
980 return setStandardMetadata<StandardMetadataType::SMPTE2086>(mMapper, bufferHandle, smpte2086);
981}
982
983status_t Gralloc5Mapper::getCta861_3(buffer_handle_t bufferHandle,
984 std::optional<ui::Cta861_3> *outCta861_3) const {
985 auto value = getStandardMetadata<StandardMetadataType::CTA861_3>(mMapper, bufferHandle);
986 if (value.has_value()) {
987 *outCta861_3 = *value;
988 return OK;
989 }
990 return UNKNOWN_TRANSACTION;
991}
992
993status_t Gralloc5Mapper::setCta861_3(buffer_handle_t bufferHandle,
994 std::optional<ui::Cta861_3> cta861_3) const {
995 return setStandardMetadata<StandardMetadataType::CTA861_3>(mMapper, bufferHandle, cta861_3);
996}
997
998status_t Gralloc5Mapper::getSmpte2094_40(
999 buffer_handle_t bufferHandle, std::optional<std::vector<uint8_t>> *outSmpte2094_40) const {
1000 auto value = getStandardMetadata<StandardMetadataType::SMPTE2094_40>(mMapper, bufferHandle);
1001 if (value.has_value()) {
1002 *outSmpte2094_40 = std::move(*value);
1003 return OK;
1004 }
1005 return UNKNOWN_TRANSACTION;
1006}
1007
1008status_t Gralloc5Mapper::setSmpte2094_40(buffer_handle_t bufferHandle,
1009 std::optional<std::vector<uint8_t>> smpte2094_40) const {
1010 return setStandardMetadata<StandardMetadataType::SMPTE2094_40>(mMapper, bufferHandle,
1011 smpte2094_40);
1012}
1013
1014status_t Gralloc5Mapper::getSmpte2094_10(
1015 buffer_handle_t bufferHandle, std::optional<std::vector<uint8_t>> *outSmpte2094_10) const {
1016 auto value = getStandardMetadata<StandardMetadataType::SMPTE2094_10>(mMapper, bufferHandle);
1017 if (value.has_value()) {
1018 *outSmpte2094_10 = std::move(*value);
1019 return OK;
1020 }
1021 return UNKNOWN_TRANSACTION;
1022}
1023
1024status_t Gralloc5Mapper::setSmpte2094_10(buffer_handle_t bufferHandle,
1025 std::optional<std::vector<uint8_t>> smpte2094_10) const {
1026 return setStandardMetadata<StandardMetadataType::SMPTE2094_10>(mMapper, bufferHandle,
1027 smpte2094_10);
1028}
1029
John Reck0ff95c92022-12-08 11:45:29 -05001030} // namespace android