1 /*
2 * Copyright 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 #undef LOG_TAG
18 #define LOG_TAG "VtsHalGraphicsMapperStableC_TargetTest"
19
20 #include <aidl/Vintf.h>
21 #include <aidl/android/hardware/graphics/allocator/AllocationError.h>
22 #include <aidl/android/hardware/graphics/allocator/AllocationResult.h>
23 #include <aidl/android/hardware/graphics/allocator/IAllocator.h>
24 #include <aidl/android/hardware/graphics/common/BufferUsage.h>
25 #include <aidl/android/hardware/graphics/common/PixelFormat.h>
26 #include <aidlcommonsupport/NativeHandle.h>
27 #include <android/binder_enums.h>
28 #include <android/binder_manager.h>
29 #include <android/dlext.h>
30 #include <android/hardware/graphics/mapper/IMapper.h>
31 #include <android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h>
32 #include <gralloctypes/Gralloc4.h>
33 #include <hidl/GtestPrinter.h>
34 #include <system/graphics.h>
35
36 #include <dlfcn.h>
37 #include <drm/drm_fourcc.h>
38 #include <gtest/gtest.h>
39 #include <vndksupport/linker.h>
40 #include <initializer_list>
41 #include <optional>
42 #include <string>
43 #include <tuple>
44 #include <vector>
45
46 using namespace aidl::android::hardware::graphics::allocator;
47 using namespace aidl::android::hardware::graphics::common;
48 using namespace android;
49 using namespace android::hardware;
50 using namespace ::android::hardware::graphics::mapper;
51
52 typedef AIMapper_Error (*AIMapper_loadIMapperFn)(AIMapper* _Nullable* _Nonnull outImplementation);
53
operator |(BufferUsage lhs,BufferUsage rhs)54 inline constexpr BufferUsage operator|(BufferUsage lhs, BufferUsage rhs) {
55 using T = std::underlying_type_t<BufferUsage>;
56 return static_cast<BufferUsage>(static_cast<T>(lhs) | static_cast<T>(rhs));
57 }
58
operator |=(BufferUsage & lhs,BufferUsage rhs)59 inline BufferUsage& operator|=(BufferUsage& lhs, BufferUsage rhs) {
60 lhs = lhs | rhs;
61 return lhs;
62 }
63
64 struct YCbCr {
65 android_ycbcr yCbCr;
66 int64_t horizontalSubSampling;
67 int64_t verticalSubSampling;
68 };
69
70 constexpr const char* STANDARD_METADATA_NAME =
71 "android.hardware.graphics.common.StandardMetadataType";
72
isStandardMetadata(AIMapper_MetadataType metadataType)73 static bool isStandardMetadata(AIMapper_MetadataType metadataType) {
74 return strcmp(STANDARD_METADATA_NAME, metadataType.name) == 0;
75 }
76
toString(const std::vector<StandardMetadataType> types)77 static std::string toString(const std::vector<StandardMetadataType> types) {
78 std::stringstream buf;
79 buf << "[";
80 for (auto type : types) {
81 buf << toString(type) << ", ";
82 }
83 buf.seekp(-2, buf.cur);
84 buf << "]";
85 return buf.str();
86 }
87
88 class BufferHandle {
89 AIMapper* mIMapper;
90 buffer_handle_t mHandle = nullptr;
91
92 public:
BufferHandle(AIMapper * mapper,native_handle_t * rawHandle)93 explicit BufferHandle(AIMapper* mapper, native_handle_t* rawHandle) : mIMapper(mapper) {
94 EXPECT_EQ(AIMAPPER_ERROR_NONE, mIMapper->v5.importBuffer(rawHandle, &mHandle));
95 }
96
BufferHandle(BufferHandle && other)97 explicit BufferHandle(BufferHandle&& other) { *this = std::move(other); }
98
operator =(BufferHandle && other)99 BufferHandle& operator=(BufferHandle&& other) noexcept {
100 reset();
101 mIMapper = other.mIMapper;
102 mHandle = other.mHandle;
103 other.mHandle = nullptr;
104 return *this;
105 }
106
~BufferHandle()107 ~BufferHandle() { reset(); }
108
operator bool() const109 constexpr explicit operator bool() const noexcept { return mHandle != nullptr; }
110
operator *() const111 buffer_handle_t operator*() const noexcept { return mHandle; }
112
reset()113 void reset() {
114 if (mHandle != nullptr) {
115 EXPECT_EQ(AIMAPPER_ERROR_NONE, mIMapper->v5.freeBuffer(mHandle));
116 mHandle = nullptr;
117 }
118 }
119 };
120
121 class BufferAllocation {
122 AIMapper* mIMapper;
123 native_handle_t* mRawHandle;
124 uint32_t mStride;
125 const BufferDescriptorInfo mInfo;
126
127 public:
128 BufferAllocation(const BufferAllocation&) = delete;
129 void operator=(const BufferAllocation&) = delete;
130
BufferAllocation(AIMapper * mapper,native_handle_t * handle,uint32_t stride,const BufferDescriptorInfo & info)131 BufferAllocation(AIMapper* mapper, native_handle_t* handle, uint32_t stride,
132 const BufferDescriptorInfo& info)
133 : mIMapper(mapper), mRawHandle(handle), mStride(stride), mInfo(info) {}
134
~BufferAllocation()135 ~BufferAllocation() {
136 if (mRawHandle == nullptr) return;
137
138 native_handle_close(mRawHandle);
139 native_handle_delete(mRawHandle);
140 }
141
stride() const142 uint32_t stride() const { return mStride; }
info() const143 const BufferDescriptorInfo& info() const { return mInfo; }
144
import()145 BufferHandle import() { return BufferHandle{mIMapper, mRawHandle}; }
146
rawHandle() const147 const native_handle_t* rawHandle() const { return mRawHandle; }
148 };
149
150 class GraphicsTestsBase {
151 private:
152 friend class BufferAllocation;
153 int32_t mIAllocatorVersion = 1;
154 std::shared_ptr<IAllocator> mAllocator;
155 AIMapper* mIMapper = nullptr;
156 AIMapper_loadIMapperFn mIMapperLoader;
157 int32_t* mIMapperHALVersion = nullptr;
158
159 protected:
Initialize(std::shared_ptr<IAllocator> allocator)160 void Initialize(std::shared_ptr<IAllocator> allocator) {
161 mAllocator = allocator;
162 ASSERT_NE(nullptr, mAllocator.get()) << "failed to get allocator service";
163 ASSERT_TRUE(mAllocator->getInterfaceVersion(&mIAllocatorVersion).isOk());
164 ASSERT_GE(mIAllocatorVersion, 2);
165 std::string mapperSuffix;
166 auto status = mAllocator->getIMapperLibrarySuffix(&mapperSuffix);
167 ASSERT_TRUE(status.isOk()) << "Failed to get IMapper library suffix";
168 std::string lib_name = "mapper." + mapperSuffix + ".so";
169 void* so = AServiceManager_openDeclaredPassthroughHal("mapper", mapperSuffix.c_str(),
170 RTLD_LOCAL | RTLD_NOW);
171 ASSERT_NE(nullptr, so) << "Failed to load " << lib_name;
172 mIMapperLoader = (AIMapper_loadIMapperFn)dlsym(so, "AIMapper_loadIMapper");
173 ASSERT_NE(nullptr, mIMapperLoader) << "AIMapper_locaIMapper missing from " << lib_name;
174 ASSERT_EQ(AIMAPPER_ERROR_NONE, mIMapperLoader(&mIMapper));
175 ASSERT_NE(mIMapper, nullptr);
176 mIMapperHALVersion = (int32_t*)dlsym(so, "ANDROID_HAL_MAPPER_VERSION");
177 }
178
179 public:
getIMapperLoader() const180 AIMapper_loadIMapperFn getIMapperLoader() const { return mIMapperLoader; }
getHalVersion() const181 int32_t* getHalVersion() const { return mIMapperHALVersion; }
182
allocate(const BufferDescriptorInfo & descriptorInfo)183 std::unique_ptr<BufferAllocation> allocate(const BufferDescriptorInfo& descriptorInfo) {
184 AllocationResult result;
185 ::ndk::ScopedAStatus status = mAllocator->allocate2(descriptorInfo, 1, &result);
186 if (!status.isOk()) {
187 status_t error = status.getExceptionCode();
188 if (error == EX_SERVICE_SPECIFIC) {
189 error = status.getServiceSpecificError();
190 EXPECT_NE(OK, error) << "Failed to set error properly";
191 } else {
192 EXPECT_EQ(OK, error) << "Allocation transport failure";
193 }
194 return nullptr;
195 } else {
196 return std::make_unique<BufferAllocation>(mIMapper, dupFromAidl(result.buffers[0]),
197 result.stride, descriptorInfo);
198 }
199 }
200
allocateGeneric()201 std::unique_ptr<BufferAllocation> allocateGeneric() {
202 return allocate({
203 .name = {"VTS_TEMP"},
204 .width = 64,
205 .height = 64,
206 .layerCount = 1,
207 .format = PixelFormat::RGBA_8888,
208 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
209 .reservedSize = 0,
210 });
211 }
212
isSupported(const BufferDescriptorInfo & descriptorInfo)213 bool isSupported(const BufferDescriptorInfo& descriptorInfo) {
214 bool ret = false;
215 EXPECT_TRUE(mAllocator->isSupported(descriptorInfo, &ret).isOk());
216 return ret;
217 }
218
mapper() const219 AIMapper* mapper() const { return mIMapper; }
220
221 template <StandardMetadataType T>
getStandardMetadata(buffer_handle_t bufferHandle)222 auto getStandardMetadata(buffer_handle_t bufferHandle)
223 -> decltype(StandardMetadata<T>::value::decode(nullptr, 0)) {
224 using Value = typename StandardMetadata<T>::value;
225 std::vector<uint8_t> buffer;
226 // Initial guess
227 buffer.resize(512);
228 int32_t sizeRequired = mapper()->v5.getStandardMetadata(
229 bufferHandle, static_cast<int64_t>(T), buffer.data(), buffer.size());
230 if (sizeRequired < 0) {
231 EXPECT_EQ(-AIMAPPER_ERROR_UNSUPPORTED, sizeRequired)
232 << "Received something other than UNSUPPORTED from valid getStandardMetadata "
233 "call";
234 return std::nullopt;
235 }
236 if (sizeRequired > buffer.size()) {
237 buffer.resize(sizeRequired);
238 sizeRequired = mapper()->v5.getStandardMetadata(bufferHandle, static_cast<int64_t>(T),
239 buffer.data(), buffer.size());
240 }
241 if (sizeRequired < 0 || sizeRequired > buffer.size()) {
242 ADD_FAILURE() << "getStandardMetadata failed, received " << sizeRequired
243 << " with buffer size " << buffer.size();
244 // Generate a fail type
245 return std::nullopt;
246 }
247 return Value::decode(buffer.data(), sizeRequired);
248 }
249
250 template <StandardMetadataType T>
setStandardMetadata(buffer_handle_t bufferHandle,const typename StandardMetadata<T>::value_type & value)251 AIMapper_Error setStandardMetadata(buffer_handle_t bufferHandle,
252 const typename StandardMetadata<T>::value_type& value) {
253 using Value = typename StandardMetadata<T>::value;
254 int32_t sizeRequired = Value::encode(value, nullptr, 0);
255 if (sizeRequired < 0) {
256 EXPECT_GE(sizeRequired, 0) << "Failed to calculate required size";
257 return static_cast<AIMapper_Error>(-sizeRequired);
258 }
259 std::vector<uint8_t> buffer;
260 buffer.resize(sizeRequired);
261 sizeRequired = Value::encode(value, buffer.data(), buffer.size());
262 if (sizeRequired < 0 || sizeRequired > buffer.size()) {
263 ADD_FAILURE() << "Failed to encode with calculated size " << sizeRequired
264 << "; buffer size" << buffer.size();
265 return static_cast<AIMapper_Error>(-sizeRequired);
266 }
267 return mapper()->v5.setStandardMetadata(bufferHandle, static_cast<int64_t>(T),
268 buffer.data(), sizeRequired);
269 }
270
verifyRGBA8888PlaneLayouts(const std::vector<PlaneLayout> & planeLayouts)271 void verifyRGBA8888PlaneLayouts(const std::vector<PlaneLayout>& planeLayouts) {
272 ASSERT_EQ(1, planeLayouts.size());
273
274 const auto& planeLayout = planeLayouts.front();
275
276 ASSERT_EQ(4, planeLayout.components.size());
277
278 int64_t offsetInBitsR = -1;
279 int64_t offsetInBitsG = -1;
280 int64_t offsetInBitsB = -1;
281 int64_t offsetInBitsA = -1;
282
283 for (const auto& component : planeLayout.components) {
284 if (!gralloc4::isStandardPlaneLayoutComponentType(component.type)) {
285 continue;
286 }
287 EXPECT_EQ(8, component.sizeInBits);
288 if (component.type.value == gralloc4::PlaneLayoutComponentType_R.value) {
289 offsetInBitsR = component.offsetInBits;
290 }
291 if (component.type.value == gralloc4::PlaneLayoutComponentType_G.value) {
292 offsetInBitsG = component.offsetInBits;
293 }
294 if (component.type.value == gralloc4::PlaneLayoutComponentType_B.value) {
295 offsetInBitsB = component.offsetInBits;
296 }
297 if (component.type.value == gralloc4::PlaneLayoutComponentType_A.value) {
298 offsetInBitsA = component.offsetInBits;
299 }
300 }
301
302 EXPECT_EQ(0, offsetInBitsR);
303 EXPECT_EQ(8, offsetInBitsG);
304 EXPECT_EQ(16, offsetInBitsB);
305 EXPECT_EQ(24, offsetInBitsA);
306
307 EXPECT_EQ(0, planeLayout.offsetInBytes);
308 EXPECT_EQ(32, planeLayout.sampleIncrementInBits);
309 // Skip testing stride because any stride is valid
310 EXPECT_LE(planeLayout.widthInSamples * planeLayout.heightInSamples * 4,
311 planeLayout.totalSizeInBytes);
312 EXPECT_EQ(1, planeLayout.horizontalSubsampling);
313 EXPECT_EQ(1, planeLayout.verticalSubsampling);
314 }
315
fillRGBA8888(uint8_t * data,uint32_t height,size_t strideInBytes,size_t widthInBytes)316 void fillRGBA8888(uint8_t* data, uint32_t height, size_t strideInBytes, size_t widthInBytes) {
317 for (uint32_t y = 0; y < height; y++) {
318 memset(data, y, widthInBytes);
319 data += strideInBytes;
320 }
321 }
322
verifyRGBA8888(const buffer_handle_t bufferHandle,const uint8_t * data,uint32_t height,size_t strideInBytes,size_t widthInBytes)323 void verifyRGBA8888(const buffer_handle_t bufferHandle, const uint8_t* data, uint32_t height,
324 size_t strideInBytes, size_t widthInBytes) {
325 auto decodeResult = getStandardMetadata<StandardMetadataType::PLANE_LAYOUTS>(bufferHandle);
326 ASSERT_TRUE(decodeResult.has_value());
327 const auto& planeLayouts = *decodeResult;
328 ASSERT_TRUE(planeLayouts.size() > 0);
329
330 verifyRGBA8888PlaneLayouts(planeLayouts);
331
332 for (uint32_t y = 0; y < height; y++) {
333 for (size_t i = 0; i < widthInBytes; i++) {
334 EXPECT_EQ(static_cast<uint8_t>(y), data[i]);
335 }
336 data += strideInBytes;
337 }
338 }
339
traverseYCbCrData(const android_ycbcr & yCbCr,int32_t width,int32_t height,int64_t hSubsampling,int64_t vSubsampling,std::function<void (uint8_t *,uint8_t)> traverseFuncion)340 void traverseYCbCrData(const android_ycbcr& yCbCr, int32_t width, int32_t height,
341 int64_t hSubsampling, int64_t vSubsampling,
342 std::function<void(uint8_t*, uint8_t)> traverseFuncion) {
343 auto yData = static_cast<uint8_t*>(yCbCr.y);
344 auto cbData = static_cast<uint8_t*>(yCbCr.cb);
345 auto crData = static_cast<uint8_t*>(yCbCr.cr);
346 auto yStride = yCbCr.ystride;
347 auto cStride = yCbCr.cstride;
348 auto chromaStep = yCbCr.chroma_step;
349
350 for (uint32_t y = 0; y < height; y++) {
351 for (uint32_t x = 0; x < width; x++) {
352 auto val = static_cast<uint8_t>(height * y + x);
353
354 traverseFuncion(yData + yStride * y + x, val);
355
356 if (y % vSubsampling == 0 && x % hSubsampling == 0) {
357 uint32_t subSampleX = x / hSubsampling;
358 uint32_t subSampleY = y / vSubsampling;
359 const auto subSampleOffset = cStride * subSampleY + chromaStep * subSampleX;
360 const auto subSampleVal =
361 static_cast<uint8_t>(height * subSampleY + subSampleX);
362
363 traverseFuncion(cbData + subSampleOffset, subSampleVal);
364 traverseFuncion(crData + subSampleOffset, subSampleVal + 1);
365 }
366 }
367 }
368 }
369
fillYCbCrData(const android_ycbcr & yCbCr,int32_t width,int32_t height,int64_t hSubsampling,int64_t vSubsampling)370 void fillYCbCrData(const android_ycbcr& yCbCr, int32_t width, int32_t height,
371 int64_t hSubsampling, int64_t vSubsampling) {
372 traverseYCbCrData(yCbCr, width, height, hSubsampling, vSubsampling,
373 [](auto address, auto fillingData) { *address = fillingData; });
374 }
375
verifyYCbCrData(const android_ycbcr & yCbCr,int32_t width,int32_t height,int64_t hSubsampling,int64_t vSubsampling)376 void verifyYCbCrData(const android_ycbcr& yCbCr, int32_t width, int32_t height,
377 int64_t hSubsampling, int64_t vSubsampling) {
378 traverseYCbCrData(
379 yCbCr, width, height, hSubsampling, vSubsampling,
380 [](auto address, auto expectedData) { EXPECT_EQ(*address, expectedData); });
381 }
382
bitsToBytes(int64_t bits)383 constexpr uint64_t bitsToBytes(int64_t bits) { return bits / 8; }
bytesToBits(int64_t bytes)384 constexpr uint64_t bytesToBits(int64_t bytes) { return bytes * 8; }
385
getAndroidYCbCr(buffer_handle_t bufferHandle,uint8_t * data,android_ycbcr * outYCbCr,int64_t * hSubsampling,int64_t * vSubsampling)386 void getAndroidYCbCr(buffer_handle_t bufferHandle, uint8_t* data, android_ycbcr* outYCbCr,
387 int64_t* hSubsampling, int64_t* vSubsampling) {
388 auto decodeResult = getStandardMetadata<StandardMetadataType::PLANE_LAYOUTS>(bufferHandle);
389 ASSERT_TRUE(decodeResult.has_value());
390 const auto& planeLayouts = *decodeResult;
391 ASSERT_TRUE(planeLayouts.size() > 0);
392
393 outYCbCr->y = nullptr;
394 outYCbCr->cb = nullptr;
395 outYCbCr->cr = nullptr;
396 outYCbCr->ystride = 0;
397 outYCbCr->cstride = 0;
398 outYCbCr->chroma_step = 0;
399
400 for (const auto& planeLayout : planeLayouts) {
401 for (const auto& planeLayoutComponent : planeLayout.components) {
402 if (!gralloc4::isStandardPlaneLayoutComponentType(planeLayoutComponent.type)) {
403 continue;
404 }
405 ASSERT_EQ(0, planeLayoutComponent.offsetInBits % 8);
406
407 uint8_t* tmpData = data + planeLayout.offsetInBytes +
408 bitsToBytes(planeLayoutComponent.offsetInBits);
409 uint64_t sampleIncrementInBytes;
410
411 auto type = static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value);
412 switch (type) {
413 case PlaneLayoutComponentType::Y:
414 ASSERT_EQ(nullptr, outYCbCr->y);
415 ASSERT_EQ(8, planeLayoutComponent.sizeInBits);
416 ASSERT_EQ(8, planeLayout.sampleIncrementInBits);
417 outYCbCr->y = tmpData;
418 outYCbCr->ystride = planeLayout.strideInBytes;
419 break;
420
421 case PlaneLayoutComponentType::CB:
422 case PlaneLayoutComponentType::CR:
423 ASSERT_EQ(0, planeLayout.sampleIncrementInBits % 8);
424
425 sampleIncrementInBytes = planeLayout.sampleIncrementInBits / 8;
426 ASSERT_TRUE(sampleIncrementInBytes == 1 || sampleIncrementInBytes == 2);
427
428 if (outYCbCr->cstride == 0 && outYCbCr->chroma_step == 0) {
429 outYCbCr->cstride = planeLayout.strideInBytes;
430 outYCbCr->chroma_step = sampleIncrementInBytes;
431 } else {
432 ASSERT_EQ(outYCbCr->cstride, planeLayout.strideInBytes);
433 ASSERT_EQ(outYCbCr->chroma_step, sampleIncrementInBytes);
434 }
435
436 if (*hSubsampling == 0 && *vSubsampling == 0) {
437 *hSubsampling = planeLayout.horizontalSubsampling;
438 *vSubsampling = planeLayout.verticalSubsampling;
439 } else {
440 ASSERT_EQ(*hSubsampling, planeLayout.horizontalSubsampling);
441 ASSERT_EQ(*vSubsampling, planeLayout.verticalSubsampling);
442 }
443
444 if (type == PlaneLayoutComponentType::CB) {
445 ASSERT_EQ(nullptr, outYCbCr->cb);
446 outYCbCr->cb = tmpData;
447 } else {
448 ASSERT_EQ(nullptr, outYCbCr->cr);
449 outYCbCr->cr = tmpData;
450 }
451 break;
452 default:
453 break;
454 };
455 }
456 }
457
458 ASSERT_NE(nullptr, outYCbCr->y);
459 ASSERT_NE(nullptr, outYCbCr->cb);
460 ASSERT_NE(nullptr, outYCbCr->cr);
461 }
462
getAndroidYCbCr_10bit(const native_handle_t * bufferHandle,uint8_t * data)463 YCbCr getAndroidYCbCr_10bit(const native_handle_t* bufferHandle, uint8_t* data) {
464 YCbCr yCbCr_10bit;
465 auto decodeResult = getStandardMetadata<StandardMetadataType::PLANE_LAYOUTS>(bufferHandle);
466 if (!decodeResult.has_value()) {
467 ADD_FAILURE() << "failed to get plane layout";
468 return YCbCr{};
469 }
470 const auto& planeLayouts = *decodeResult;
471 EXPECT_EQ(2, planeLayouts.size());
472 EXPECT_EQ(1, planeLayouts[0].components.size());
473 EXPECT_EQ(2, planeLayouts[1].components.size());
474
475 yCbCr_10bit.yCbCr.y = nullptr;
476 yCbCr_10bit.yCbCr.cb = nullptr;
477 yCbCr_10bit.yCbCr.cr = nullptr;
478 yCbCr_10bit.yCbCr.ystride = 0;
479 yCbCr_10bit.yCbCr.cstride = 0;
480 yCbCr_10bit.yCbCr.chroma_step = 0;
481 int64_t cb_offset = 0;
482 int64_t cr_offset = 0;
483
484 for (const auto& planeLayout : planeLayouts) {
485 for (const auto& planeLayoutComponent : planeLayout.components) {
486 if (!gralloc4::isStandardPlaneLayoutComponentType(planeLayoutComponent.type)) {
487 continue;
488 }
489
490 uint8_t* tmpData = data + planeLayout.offsetInBytes +
491 bitsToBytes(planeLayoutComponent.offsetInBits);
492 uint64_t sampleIncrementInBytes = 0;
493 auto type = static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value);
494 switch (type) {
495 case PlaneLayoutComponentType::Y:
496 // For specs refer to:
497 // https://docs.microsoft.com/en-us/windows/win32/medfound/10-bit-and-16-bit-yuv-video-formats
498 EXPECT_EQ(6, planeLayoutComponent.offsetInBits);
499 EXPECT_EQ(nullptr, yCbCr_10bit.yCbCr.y);
500 EXPECT_EQ(10, planeLayoutComponent.sizeInBits);
501 EXPECT_EQ(16, planeLayout.sampleIncrementInBits);
502
503 yCbCr_10bit.yCbCr.y = tmpData;
504 yCbCr_10bit.yCbCr.ystride = planeLayout.strideInBytes;
505 break;
506
507 case PlaneLayoutComponentType::CB:
508 case PlaneLayoutComponentType::CR:
509 sampleIncrementInBytes = bitsToBytes(planeLayout.sampleIncrementInBits);
510 EXPECT_EQ(4, sampleIncrementInBytes);
511
512 if (yCbCr_10bit.yCbCr.cstride == 0 && yCbCr_10bit.yCbCr.chroma_step == 0) {
513 yCbCr_10bit.yCbCr.cstride = planeLayout.strideInBytes;
514 yCbCr_10bit.yCbCr.chroma_step = sampleIncrementInBytes;
515 } else {
516 EXPECT_EQ(yCbCr_10bit.yCbCr.cstride, planeLayout.strideInBytes);
517 EXPECT_EQ(yCbCr_10bit.yCbCr.chroma_step, sampleIncrementInBytes);
518 }
519
520 if (yCbCr_10bit.horizontalSubSampling == 0 &&
521 yCbCr_10bit.verticalSubSampling == 0) {
522 yCbCr_10bit.horizontalSubSampling = planeLayout.horizontalSubsampling;
523 yCbCr_10bit.verticalSubSampling = planeLayout.verticalSubsampling;
524 } else {
525 EXPECT_EQ(yCbCr_10bit.horizontalSubSampling,
526 planeLayout.horizontalSubsampling);
527 EXPECT_EQ(yCbCr_10bit.verticalSubSampling,
528 planeLayout.verticalSubsampling);
529 }
530
531 if (type == PlaneLayoutComponentType::CB) {
532 EXPECT_EQ(nullptr, yCbCr_10bit.yCbCr.cb);
533 yCbCr_10bit.yCbCr.cb = tmpData;
534 cb_offset = planeLayoutComponent.offsetInBits;
535 } else {
536 EXPECT_EQ(nullptr, yCbCr_10bit.yCbCr.cr);
537 yCbCr_10bit.yCbCr.cr = tmpData;
538 cr_offset = planeLayoutComponent.offsetInBits;
539 }
540 break;
541 default:
542 break;
543 }
544 }
545 }
546
547 EXPECT_EQ(cb_offset + bytesToBits(2), cr_offset);
548 EXPECT_NE(nullptr, yCbCr_10bit.yCbCr.y);
549 EXPECT_NE(nullptr, yCbCr_10bit.yCbCr.cb);
550 EXPECT_NE(nullptr, yCbCr_10bit.yCbCr.cr);
551 return yCbCr_10bit;
552 }
553 };
554
555 class GraphicsMapperStableCTests
556 : public GraphicsTestsBase,
557 public ::testing::TestWithParam<std::tuple<std::string, std::shared_ptr<IAllocator>>> {
558 public:
SetUp()559 void SetUp() override { Initialize(std::get<1>(GetParam())); }
560
TearDown()561 void TearDown() override {}
562 };
563
TEST_P(GraphicsMapperStableCTests,VersionChecks)564 TEST_P(GraphicsMapperStableCTests, VersionChecks) {
565 ASSERT_NE(nullptr, getHalVersion()) << "Resolving ANDROID_HAL_MAPPER_VERSION symbol failed";
566 int32_t halVersion = *getHalVersion();
567 EXPECT_EQ(halVersion, AIMAPPER_VERSION_5) << "Unrecognized ANDROID_HAL_MAPPER_VERSION";
568 EXPECT_EQ(mapper()->version, AIMAPPER_VERSION_5) << "Unrecognized AIMapper::version";
569 EXPECT_EQ(halVersion, mapper()->version)
570 << "AIMapper version & ANDROID_HAL_MAPPER_VERSION don't agree";
571 }
572
TEST_P(GraphicsMapperStableCTests,AllV5CallbacksDefined)573 TEST_P(GraphicsMapperStableCTests, AllV5CallbacksDefined) {
574 ASSERT_GE(mapper()->version, AIMAPPER_VERSION_5);
575
576 EXPECT_TRUE(mapper()->v5.importBuffer);
577 EXPECT_TRUE(mapper()->v5.freeBuffer);
578 EXPECT_TRUE(mapper()->v5.getTransportSize);
579 EXPECT_TRUE(mapper()->v5.lock);
580 EXPECT_TRUE(mapper()->v5.unlock);
581 EXPECT_TRUE(mapper()->v5.flushLockedBuffer);
582 EXPECT_TRUE(mapper()->v5.rereadLockedBuffer);
583 EXPECT_TRUE(mapper()->v5.getMetadata);
584 EXPECT_TRUE(mapper()->v5.getStandardMetadata);
585 EXPECT_TRUE(mapper()->v5.setMetadata);
586 EXPECT_TRUE(mapper()->v5.setStandardMetadata);
587 EXPECT_TRUE(mapper()->v5.listSupportedMetadataTypes);
588 EXPECT_TRUE(mapper()->v5.dumpBuffer);
589 EXPECT_TRUE(mapper()->v5.getReservedRegion);
590 }
591
TEST_P(GraphicsMapperStableCTests,DualLoadIsIdentical)592 TEST_P(GraphicsMapperStableCTests, DualLoadIsIdentical) {
593 ASSERT_GE(mapper()->version, AIMAPPER_VERSION_5);
594 AIMapper* secondMapper;
595 ASSERT_EQ(AIMAPPER_ERROR_NONE, getIMapperLoader()(&secondMapper));
596
597 EXPECT_EQ(secondMapper->v5.importBuffer, mapper()->v5.importBuffer);
598 EXPECT_EQ(secondMapper->v5.freeBuffer, mapper()->v5.freeBuffer);
599 EXPECT_EQ(secondMapper->v5.getTransportSize, mapper()->v5.getTransportSize);
600 EXPECT_EQ(secondMapper->v5.lock, mapper()->v5.lock);
601 EXPECT_EQ(secondMapper->v5.unlock, mapper()->v5.unlock);
602 EXPECT_EQ(secondMapper->v5.flushLockedBuffer, mapper()->v5.flushLockedBuffer);
603 EXPECT_EQ(secondMapper->v5.rereadLockedBuffer, mapper()->v5.rereadLockedBuffer);
604 EXPECT_EQ(secondMapper->v5.getMetadata, mapper()->v5.getMetadata);
605 EXPECT_EQ(secondMapper->v5.getStandardMetadata, mapper()->v5.getStandardMetadata);
606 EXPECT_EQ(secondMapper->v5.setMetadata, mapper()->v5.setMetadata);
607 EXPECT_EQ(secondMapper->v5.setStandardMetadata, mapper()->v5.setStandardMetadata);
608 EXPECT_EQ(secondMapper->v5.listSupportedMetadataTypes, mapper()->v5.listSupportedMetadataTypes);
609 EXPECT_EQ(secondMapper->v5.dumpBuffer, mapper()->v5.dumpBuffer);
610 EXPECT_EQ(secondMapper->v5.getReservedRegion, mapper()->v5.getReservedRegion);
611 }
612
TEST_P(GraphicsMapperStableCTests,CanAllocate)613 TEST_P(GraphicsMapperStableCTests, CanAllocate) {
614 auto buffer = allocate({
615 .name = {"VTS_TEMP"},
616 .width = 64,
617 .height = 64,
618 .layerCount = 1,
619 .format = PixelFormat::RGBA_8888,
620 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
621 .reservedSize = 0,
622 });
623 ASSERT_NE(nullptr, buffer.get());
624 EXPECT_GE(buffer->stride(), 64);
625 }
626
TEST_P(GraphicsMapperStableCTests,ImportFreeBuffer)627 TEST_P(GraphicsMapperStableCTests, ImportFreeBuffer) {
628 auto buffer = allocate({
629 .name = {"VTS_TEMP"},
630 .width = 64,
631 .height = 64,
632 .layerCount = 1,
633 .format = PixelFormat::RGBA_8888,
634 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
635 .reservedSize = 0,
636 });
637 ASSERT_NE(nullptr, buffer.get());
638 EXPECT_GE(buffer->stride(), 64);
639
640 {
641 auto import1 = buffer->import();
642 auto import2 = buffer->import();
643 EXPECT_TRUE(import1);
644 EXPECT_TRUE(import2);
645 EXPECT_NE(*import1, *import2);
646 }
647 }
648
649 /**
650 * Test IMapper::importBuffer and IMapper::freeBuffer cross mapper instances.
651 */
TEST_P(GraphicsMapperStableCTests,ImportFreeBufferSingleton)652 TEST_P(GraphicsMapperStableCTests, ImportFreeBufferSingleton) {
653 auto buffer = allocate({
654 .name = {"VTS_TEMP"},
655 .width = 64,
656 .height = 64,
657 .layerCount = 1,
658 .format = PixelFormat::RGBA_8888,
659 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
660 .reservedSize = 0,
661 });
662 ASSERT_NE(nullptr, buffer.get());
663 EXPECT_GE(buffer->stride(), 64);
664
665 buffer_handle_t bufferHandle = nullptr;
666 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.importBuffer(buffer->rawHandle(), &bufferHandle));
667 ASSERT_NE(nullptr, bufferHandle);
668
669 AIMapper* secondMapper;
670 ASSERT_EQ(AIMAPPER_ERROR_NONE, getIMapperLoader()(&secondMapper));
671 ASSERT_EQ(AIMAPPER_ERROR_NONE, secondMapper->v5.freeBuffer(bufferHandle));
672 }
673
674 /**
675 * Test IMapper::importBuffer with invalid buffers.
676 */
TEST_P(GraphicsMapperStableCTests,ImportBufferNegative)677 TEST_P(GraphicsMapperStableCTests, ImportBufferNegative) {
678 native_handle_t* invalidHandle = nullptr;
679 buffer_handle_t bufferHandle = nullptr;
680 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.importBuffer(invalidHandle, &bufferHandle))
681 << "importBuffer with nullptr did not fail with BAD_BUFFER";
682
683 invalidHandle = native_handle_create(0, 0);
684 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.importBuffer(invalidHandle, &bufferHandle))
685 << "importBuffer with invalid handle did not fail with BAD_BUFFER";
686 native_handle_delete(invalidHandle);
687 }
688
689 /**
690 * Test IMapper::freeBuffer with invalid buffers.
691 */
TEST_P(GraphicsMapperStableCTests,FreeBufferNegative)692 TEST_P(GraphicsMapperStableCTests, FreeBufferNegative) {
693 native_handle_t* bufferHandle = nullptr;
694 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.freeBuffer(bufferHandle))
695 << "freeBuffer with nullptr did not fail with BAD_BUFFER";
696
697 bufferHandle = native_handle_create(0, 0);
698 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.freeBuffer(bufferHandle))
699 << "freeBuffer with invalid handle did not fail with BAD_BUFFER";
700 native_handle_delete(bufferHandle);
701
702 auto buffer = allocateGeneric();
703 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.freeBuffer(buffer->rawHandle()))
704 << "freeBuffer with un-imported handle did not fail with BAD_BUFFER";
705 }
706
707 /**
708 * Test IMapper::lock and IMapper::unlock.
709 */
TEST_P(GraphicsMapperStableCTests,LockUnlockBasic)710 TEST_P(GraphicsMapperStableCTests, LockUnlockBasic) {
711 constexpr auto usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN;
712 auto buffer = allocate({
713 .name = {"VTS_TEMP"},
714 .width = 64,
715 .height = 64,
716 .layerCount = 1,
717 .format = PixelFormat::RGBA_8888,
718 .usage = usage,
719 .reservedSize = 0,
720 });
721 ASSERT_NE(nullptr, buffer.get());
722
723 // lock buffer for writing
724 const auto& info = buffer->info();
725 const auto stride = buffer->stride();
726 const ARect region{0, 0, info.width, info.height};
727 auto handle = buffer->import();
728 uint8_t* data = nullptr;
729 ASSERT_EQ(AIMAPPER_ERROR_NONE,
730 mapper()->v5.lock(*handle, static_cast<int64_t>(usage), region, -1, (void**)&data));
731
732 // RGBA_8888
733 fillRGBA8888(data, info.height, stride * 4, info.width * 4);
734
735 int releaseFence = -1;
736 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
737
738 // lock again for reading
739 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(usage), region,
740 releaseFence, (void**)&data));
741 releaseFence = -1;
742
743 ASSERT_NO_FATAL_FAILURE(verifyRGBA8888(*handle, data, info.height, stride * 4, info.width * 4));
744
745 releaseFence = -1;
746 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
747 if (releaseFence != -1) {
748 close(releaseFence);
749 }
750 }
751
752 /**
753 * Test IMapper::lock and IMapper::unlock with no CPU usage requested.
754 */
TEST_P(GraphicsMapperStableCTests,LockUnlockNoCPUUsage)755 TEST_P(GraphicsMapperStableCTests, LockUnlockNoCPUUsage) {
756 constexpr auto usage = BufferUsage::CPU_READ_RARELY | BufferUsage::CPU_WRITE_NEVER;
757 auto buffer = allocate({
758 .name = {"VTS_TEMP"},
759 .width = 64,
760 .height = 64,
761 .layerCount = 1,
762 .format = PixelFormat::RGBA_8888,
763 .usage = usage,
764 .reservedSize = 0,
765 });
766 ASSERT_NE(nullptr, buffer.get());
767
768 // lock buffer for writing
769 const auto& info = buffer->info();
770 const ARect region{0, 0, info.width, info.height};
771 auto handle = buffer->import();
772 uint8_t* data = nullptr;
773
774 EXPECT_EQ(AIMAPPER_ERROR_BAD_VALUE, mapper()->v5.lock(*handle, 0, region, -1, (void**)&data))
775 << "Locking with 0 access succeeded";
776
777 int releaseFence = -1;
778 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.unlock(*handle, &releaseFence))
779 << "Unlocking not locked buffer succeeded";
780 if (releaseFence != -1) {
781 close(releaseFence);
782 }
783 }
784
785 /**
786 * Test multiple operations associated with different color formats
787 */
TEST_P(GraphicsMapperStableCTests,Lock_YCRCB_420_SP)788 TEST_P(GraphicsMapperStableCTests, Lock_YCRCB_420_SP) {
789 BufferDescriptorInfo info{
790 .name = {"VTS_TEMP"},
791 .width = 64,
792 .height = 64,
793 .layerCount = 1,
794 .format = PixelFormat::YCRCB_420_SP,
795 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
796 .reservedSize = 0,
797 };
798 auto buffer = allocate(info);
799 if (!buffer) {
800 ASSERT_FALSE(isSupported(info));
801 GTEST_SUCCEED() << "YCRCB_420_SP format is unsupported";
802 return;
803 }
804
805 // lock buffer for writing
806 const ARect region{0, 0, info.width, info.height};
807 auto handle = buffer->import();
808 uint8_t* data = nullptr;
809 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
810 region, -1, (void**)&data));
811
812 android_ycbcr yCbCr;
813 int64_t hSubsampling = 0;
814 int64_t vSubsampling = 0;
815 ASSERT_NO_FATAL_FAILURE(getAndroidYCbCr(*handle, data, &yCbCr, &hSubsampling, &vSubsampling));
816
817 constexpr uint32_t kCbCrSubSampleFactor = 2;
818 ASSERT_EQ(kCbCrSubSampleFactor, hSubsampling);
819 ASSERT_EQ(kCbCrSubSampleFactor, vSubsampling);
820
821 auto cbData = static_cast<uint8_t*>(yCbCr.cb);
822 auto crData = static_cast<uint8_t*>(yCbCr.cr);
823 ASSERT_EQ(crData + 1, cbData);
824 ASSERT_EQ(2, yCbCr.chroma_step);
825
826 fillYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
827
828 int releaseFence = -1;
829 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
830
831 // lock again for reading
832 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
833 region, releaseFence, (void**)&data));
834 releaseFence = -1;
835
836 ASSERT_NO_FATAL_FAILURE(getAndroidYCbCr(*handle, data, &yCbCr, &hSubsampling, &vSubsampling));
837
838 verifyYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
839
840 releaseFence = -1;
841 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
842 if (releaseFence != -1) {
843 close(releaseFence);
844 }
845 }
846
TEST_P(GraphicsMapperStableCTests,YV12SubsampleMetadata)847 TEST_P(GraphicsMapperStableCTests, YV12SubsampleMetadata) {
848 BufferDescriptorInfo info{
849 .name = {"VTS_TEMP"},
850 .width = 64,
851 .height = 64,
852 .layerCount = 1,
853 .format = PixelFormat::YV12,
854 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
855 .reservedSize = 0,
856 };
857 auto buffer = allocate(info);
858 ASSERT_NE(nullptr, buffer.get());
859
860 // lock buffer for writing
861 const ARect region{0, 0, info.width, info.height};
862 auto handle = buffer->import();
863 uint8_t* data = nullptr;
864 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
865 region, -1, (void**)&data));
866
867 auto decodeResult = getStandardMetadata<StandardMetadataType::PLANE_LAYOUTS>(*handle);
868 ASSERT_TRUE(decodeResult.has_value());
869 const auto& planeLayouts = *decodeResult;
870
871 ASSERT_EQ(3, planeLayouts.size());
872
873 auto yPlane = planeLayouts[0];
874 auto crPlane = planeLayouts[1];
875 auto cbPlane = planeLayouts[2];
876
877 constexpr uint32_t kCbCrSubSampleFactor = 2;
878 EXPECT_EQ(kCbCrSubSampleFactor, crPlane.horizontalSubsampling);
879 EXPECT_EQ(kCbCrSubSampleFactor, crPlane.verticalSubsampling);
880
881 EXPECT_EQ(kCbCrSubSampleFactor, cbPlane.horizontalSubsampling);
882 EXPECT_EQ(kCbCrSubSampleFactor, cbPlane.verticalSubsampling);
883
884 const long chromaSampleWidth = info.width / kCbCrSubSampleFactor;
885 const long chromaSampleHeight = info.height / kCbCrSubSampleFactor;
886
887 EXPECT_EQ(info.width, yPlane.widthInSamples);
888 EXPECT_EQ(info.height, yPlane.heightInSamples);
889
890 EXPECT_EQ(chromaSampleWidth, crPlane.widthInSamples);
891 EXPECT_EQ(chromaSampleHeight, crPlane.heightInSamples);
892
893 EXPECT_EQ(chromaSampleWidth, cbPlane.widthInSamples);
894 EXPECT_EQ(chromaSampleHeight, cbPlane.heightInSamples);
895
896 EXPECT_LE(crPlane.widthInSamples, crPlane.strideInBytes);
897 EXPECT_LE(cbPlane.widthInSamples, cbPlane.strideInBytes);
898
899 int releaseFence = -1;
900 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
901 if (releaseFence != -1) {
902 close(releaseFence);
903 }
904 }
905
TEST_P(GraphicsMapperStableCTests,Lock_YV12)906 TEST_P(GraphicsMapperStableCTests, Lock_YV12) {
907 BufferDescriptorInfo info{
908 .name = {"VTS_TEMP"},
909 .width = 64,
910 .height = 64,
911 .layerCount = 1,
912 .format = PixelFormat::YV12,
913 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
914 .reservedSize = 0,
915 };
916 auto buffer = allocate(info);
917 ASSERT_NE(nullptr, buffer.get());
918
919 // lock buffer for writing
920 const ARect region{0, 0, info.width, info.height};
921 auto handle = buffer->import();
922 uint8_t* data = nullptr;
923 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
924 region, -1, (void**)&data));
925
926 android_ycbcr yCbCr;
927 int64_t hSubsampling = 0;
928 int64_t vSubsampling = 0;
929 ASSERT_NO_FATAL_FAILURE(getAndroidYCbCr(*handle, data, &yCbCr, &hSubsampling, &vSubsampling));
930
931 constexpr uint32_t kCbCrSubSampleFactor = 2;
932 ASSERT_EQ(kCbCrSubSampleFactor, hSubsampling);
933 ASSERT_EQ(kCbCrSubSampleFactor, vSubsampling);
934
935 auto cbData = static_cast<uint8_t*>(yCbCr.cb);
936 auto crData = static_cast<uint8_t*>(yCbCr.cr);
937 ASSERT_EQ(crData + yCbCr.cstride * info.height / vSubsampling, cbData);
938 ASSERT_EQ(1, yCbCr.chroma_step);
939
940 fillYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
941
942 int releaseFence = -1;
943 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
944
945 // lock again for reading
946 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
947 region, releaseFence, (void**)&data));
948 releaseFence = -1;
949
950 ASSERT_NO_FATAL_FAILURE(getAndroidYCbCr(*handle, data, &yCbCr, &hSubsampling, &vSubsampling));
951
952 verifyYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
953
954 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
955 if (releaseFence != -1) {
956 close(releaseFence);
957 }
958 }
959
TEST_P(GraphicsMapperStableCTests,Lock_YCBCR_420_888)960 TEST_P(GraphicsMapperStableCTests, Lock_YCBCR_420_888) {
961 BufferDescriptorInfo info{
962 .name = {"VTS_TEMP"},
963 .width = 64,
964 .height = 64,
965 .layerCount = 1,
966 .format = PixelFormat::YCBCR_420_888,
967 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
968 .reservedSize = 0,
969 };
970 auto buffer = allocate(info);
971 ASSERT_NE(nullptr, buffer.get());
972
973 // lock buffer for writing
974 const ARect region{0, 0, info.width, info.height};
975 auto handle = buffer->import();
976 uint8_t* data = nullptr;
977 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
978 region, -1, (void**)&data));
979
980 android_ycbcr yCbCr;
981 int64_t hSubsampling = 0;
982 int64_t vSubsampling = 0;
983 ASSERT_NO_FATAL_FAILURE(getAndroidYCbCr(*handle, data, &yCbCr, &hSubsampling, &vSubsampling));
984
985 constexpr uint32_t kCbCrSubSampleFactor = 2;
986 ASSERT_EQ(kCbCrSubSampleFactor, hSubsampling);
987 ASSERT_EQ(kCbCrSubSampleFactor, vSubsampling);
988
989 fillYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
990
991 int releaseFence = -1;
992 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
993
994 // lock again for reading
995 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
996 region, releaseFence, (void**)&data));
997 releaseFence = -1;
998
999 ASSERT_NO_FATAL_FAILURE(getAndroidYCbCr(*handle, data, &yCbCr, &hSubsampling, &vSubsampling));
1000
1001 verifyYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
1002
1003 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
1004 if (releaseFence != -1) {
1005 close(releaseFence);
1006 }
1007 }
1008
TEST_P(GraphicsMapperStableCTests,Lock_RAW10)1009 TEST_P(GraphicsMapperStableCTests, Lock_RAW10) {
1010 BufferDescriptorInfo info{
1011 .name = {"VTS_TEMP"},
1012 .width = 64,
1013 .height = 64,
1014 .layerCount = 1,
1015 .format = PixelFormat::RAW10,
1016 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
1017 .reservedSize = 0,
1018 };
1019 auto buffer = allocate(info);
1020 if (!buffer) {
1021 ASSERT_FALSE(isSupported(info));
1022 GTEST_SUCCEED() << "RAW10 format is unsupported";
1023 return;
1024 }
1025
1026 // lock buffer for writing
1027 const ARect region{0, 0, info.width, info.height};
1028 auto handle = buffer->import();
1029 uint8_t* data = nullptr;
1030 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
1031 region, -1, (void**)&data));
1032
1033 auto decodeResult = getStandardMetadata<StandardMetadataType::PLANE_LAYOUTS>(*handle);
1034 ASSERT_TRUE(decodeResult.has_value());
1035 const auto& planeLayouts = *decodeResult;
1036
1037 ASSERT_EQ(1, planeLayouts.size());
1038 auto planeLayout = planeLayouts[0];
1039
1040 EXPECT_EQ(0, planeLayout.sampleIncrementInBits);
1041 EXPECT_EQ(1, planeLayout.horizontalSubsampling);
1042 EXPECT_EQ(1, planeLayout.verticalSubsampling);
1043
1044 ASSERT_EQ(1, planeLayout.components.size());
1045 auto planeLayoutComponent = planeLayout.components[0];
1046
1047 EXPECT_EQ(PlaneLayoutComponentType::RAW,
1048 static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value));
1049 EXPECT_EQ(0, planeLayoutComponent.offsetInBits % 8);
1050 EXPECT_EQ(-1, planeLayoutComponent.sizeInBits);
1051
1052 int releaseFence = -1;
1053 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
1054 if (releaseFence != -1) {
1055 close(releaseFence);
1056 }
1057 }
1058
TEST_P(GraphicsMapperStableCTests,Lock_RAW12)1059 TEST_P(GraphicsMapperStableCTests, Lock_RAW12) {
1060 BufferDescriptorInfo info{
1061 .name = {"VTS_TEMP"},
1062 .width = 64,
1063 .height = 64,
1064 .layerCount = 1,
1065 .format = PixelFormat::RAW12,
1066 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
1067 .reservedSize = 0,
1068 };
1069 auto buffer = allocate(info);
1070 if (!buffer) {
1071 ASSERT_FALSE(isSupported(info));
1072 GTEST_SUCCEED() << "RAW12 format is unsupported";
1073 return;
1074 }
1075
1076 // lock buffer for writing
1077 const ARect region{0, 0, info.width, info.height};
1078 auto handle = buffer->import();
1079 uint8_t* data = nullptr;
1080 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
1081 region, -1, (void**)&data));
1082
1083 auto decodeResult = getStandardMetadata<StandardMetadataType::PLANE_LAYOUTS>(*handle);
1084 ASSERT_TRUE(decodeResult.has_value());
1085 const auto& planeLayouts = *decodeResult;
1086
1087 ASSERT_EQ(1, planeLayouts.size());
1088 auto planeLayout = planeLayouts[0];
1089
1090 EXPECT_EQ(0, planeLayout.sampleIncrementInBits);
1091 EXPECT_EQ(1, planeLayout.horizontalSubsampling);
1092 EXPECT_EQ(1, planeLayout.verticalSubsampling);
1093
1094 ASSERT_EQ(1, planeLayout.components.size());
1095 auto planeLayoutComponent = planeLayout.components[0];
1096
1097 EXPECT_EQ(PlaneLayoutComponentType::RAW,
1098 static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value));
1099 EXPECT_EQ(0, planeLayoutComponent.offsetInBits % 8);
1100 EXPECT_EQ(-1, planeLayoutComponent.sizeInBits);
1101
1102 int releaseFence = -1;
1103 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
1104 if (releaseFence != -1) {
1105 close(releaseFence);
1106 }
1107 }
1108
TEST_P(GraphicsMapperStableCTests,Lock_YCBCR_P010)1109 TEST_P(GraphicsMapperStableCTests, Lock_YCBCR_P010) {
1110 BufferDescriptorInfo info{
1111 .name = {"VTS_TEMP"},
1112 .width = 64,
1113 .height = 64,
1114 .layerCount = 1,
1115 .format = PixelFormat::YCBCR_P010,
1116 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
1117 .reservedSize = 0,
1118 };
1119 auto buffer = allocate(info);
1120 if (!buffer) {
1121 ASSERT_FALSE(isSupported(info));
1122 GTEST_SUCCEED() << "YCBCR_P010 format is unsupported";
1123 return;
1124 }
1125
1126 // lock buffer for writing
1127 const ARect region{0, 0, info.width, info.height};
1128 auto handle = buffer->import();
1129 uint8_t* data = nullptr;
1130 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
1131 region, -1, (void**)&data));
1132
1133 YCbCr yCbCr;
1134 ASSERT_NO_FATAL_FAILURE(yCbCr = getAndroidYCbCr_10bit(*handle, data));
1135
1136 constexpr uint32_t kCbCrSubSampleFactor = 2;
1137 ASSERT_EQ(kCbCrSubSampleFactor, yCbCr.horizontalSubSampling);
1138 ASSERT_EQ(kCbCrSubSampleFactor, yCbCr.verticalSubSampling);
1139
1140 ASSERT_EQ(0, info.height % 2);
1141
1142 // fill the data
1143 fillYCbCrData(yCbCr.yCbCr, info.width, info.height, yCbCr.horizontalSubSampling,
1144 yCbCr.verticalSubSampling);
1145 // verify the YCbCr data
1146 verifyYCbCrData(yCbCr.yCbCr, info.width, info.height, yCbCr.horizontalSubSampling,
1147 yCbCr.verticalSubSampling);
1148
1149 int releaseFence = -1;
1150 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
1151 if (releaseFence != -1) {
1152 close(releaseFence);
1153 }
1154 }
1155
TEST_P(GraphicsMapperStableCTests,Lock_YCBCR_P210)1156 TEST_P(GraphicsMapperStableCTests, Lock_YCBCR_P210) {
1157 BufferDescriptorInfo info{
1158 .name = {"VTS_TEMP"},
1159 .width = 64,
1160 .height = 64,
1161 .layerCount = 1,
1162 .format = PixelFormat::YCBCR_P210,
1163 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
1164 .reservedSize = 0,
1165 };
1166 auto buffer = allocate(info);
1167 if (!buffer) {
1168 ASSERT_FALSE(isSupported(info));
1169 GTEST_SUCCEED() << "YCBCR_P210 format is unsupported";
1170 return;
1171 }
1172
1173 // lock buffer for writing
1174 const ARect region{0, 0, info.width, info.height};
1175 auto handle = buffer->import();
1176 uint8_t *data = nullptr;
1177 ASSERT_EQ(AIMAPPER_ERROR_NONE,
1178 mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage), region,
1179 -1, (void **)&data));
1180
1181 YCbCr yCbCr;
1182 ASSERT_NO_FATAL_FAILURE(yCbCr = getAndroidYCbCr_10bit(*handle, data));
1183
1184 constexpr uint32_t kCbCrSubSampleFactor = 2;
1185 ASSERT_EQ(kCbCrSubSampleFactor, yCbCr.horizontalSubSampling);
1186 ASSERT_EQ(1, yCbCr.verticalSubSampling);
1187
1188 ASSERT_EQ(0, info.height % 2);
1189
1190 // fill the data
1191 fillYCbCrData(yCbCr.yCbCr, info.width, info.height,
1192 yCbCr.horizontalSubSampling, yCbCr.verticalSubSampling);
1193 // verify the YCbCr data
1194 verifyYCbCrData(yCbCr.yCbCr, info.width, info.height,
1195 yCbCr.horizontalSubSampling, yCbCr.verticalSubSampling);
1196
1197 int releaseFence = -1;
1198 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
1199 if (releaseFence != -1) {
1200 close(releaseFence);
1201 }
1202 }
1203
TEST_P(GraphicsMapperStableCTests,LockBadAccessRegion)1204 TEST_P(GraphicsMapperStableCTests, LockBadAccessRegion) {
1205 auto buffer = allocateGeneric();
1206 ASSERT_NE(nullptr, buffer);
1207 const auto& info = buffer->info();
1208
1209 // lock buffer for writing
1210 const ARect region{0, 0, info.width * 2, info.height * 2};
1211 auto handle = buffer->import();
1212 uint8_t* data = nullptr;
1213 EXPECT_EQ(AIMAPPER_ERROR_BAD_VALUE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
1214 region, -1, (void**)&data));
1215 }
1216
TEST_P(GraphicsMapperStableCTests,UnlockNegative)1217 TEST_P(GraphicsMapperStableCTests, UnlockNegative) {
1218 native_handle_t* invalidHandle = nullptr;
1219 int releaseFence = -1;
1220 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.unlock(invalidHandle, &releaseFence))
1221 << "unlock with nullptr did not fail with BAD_BUFFER";
1222
1223 invalidHandle = native_handle_create(0, 0);
1224 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.unlock(invalidHandle, &releaseFence))
1225 << "unlock with invalid handle did not fail with BAD_BUFFER";
1226 native_handle_delete(invalidHandle);
1227
1228 auto buffer = allocateGeneric();
1229 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.unlock(buffer->rawHandle(), &releaseFence))
1230 << "unlock with un-imported handle did not fail with BAD_BUFFER";
1231 }
1232
TEST_P(GraphicsMapperStableCTests,UnlockNotImported)1233 TEST_P(GraphicsMapperStableCTests, UnlockNotImported) {
1234 int releaseFence = -1;
1235 auto buffer = allocateGeneric();
1236 ASSERT_TRUE(buffer);
1237 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.unlock(buffer->rawHandle(), &releaseFence))
1238 << "unlock with un-imported handle did not fail with BAD_BUFFER";
1239 }
1240
TEST_P(GraphicsMapperStableCTests,UnlockNotLocked)1241 TEST_P(GraphicsMapperStableCTests, UnlockNotLocked) {
1242 int releaseFence = -1;
1243 auto buffer = allocateGeneric();
1244 ASSERT_TRUE(buffer);
1245 auto bufferHandle = buffer->import();
1246 ASSERT_TRUE(bufferHandle);
1247 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.unlock(*bufferHandle, &releaseFence))
1248 << "unlock with unlocked handle did not fail with BAD_BUFFER";
1249 }
1250
TEST_P(GraphicsMapperStableCTests,LockUnlockNested)1251 TEST_P(GraphicsMapperStableCTests, LockUnlockNested) {
1252 auto buffer = allocateGeneric();
1253 ASSERT_TRUE(buffer);
1254 auto bufferHandle = buffer->import();
1255 ASSERT_TRUE(bufferHandle);
1256 const ARect region{0, 0, buffer->info().width, buffer->info().height};
1257 auto usage = static_cast<int64_t>(buffer->info().usage);
1258 auto handle = buffer->import();
1259 uint8_t* data = nullptr;
1260 EXPECT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, usage, region, -1, (void**)&data));
1261 EXPECT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, usage, region, -1, (void**)&data))
1262 << "Second lock failed";
1263 int releaseFence = -1;
1264 EXPECT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
1265 if (releaseFence != -1) {
1266 close(releaseFence);
1267 releaseFence = -1;
1268 }
1269 EXPECT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence))
1270 << "Second unlock failed";
1271 if (releaseFence != -1) {
1272 close(releaseFence);
1273 releaseFence = -1;
1274 }
1275 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.unlock(*handle, &releaseFence))
1276 << "Third, unmatched, unlock should have failed with BAD_BUFFER";
1277 }
1278
TEST_P(GraphicsMapperStableCTests,FlushRereadBasic)1279 TEST_P(GraphicsMapperStableCTests, FlushRereadBasic) {
1280 auto buffer = allocateGeneric();
1281 ASSERT_TRUE(buffer);
1282 auto bufferHandle = buffer->import();
1283 ASSERT_TRUE(bufferHandle);
1284 const auto& info = buffer->info();
1285 const auto stride = buffer->stride();
1286 const ARect region{0, 0, buffer->info().width, buffer->info().height};
1287
1288 auto writeHandle = buffer->import();
1289 auto readHandle = buffer->import();
1290 ASSERT_TRUE(writeHandle && readHandle);
1291
1292 // lock buffer for writing
1293
1294 uint8_t* writeData;
1295 EXPECT_EQ(AIMAPPER_ERROR_NONE,
1296 mapper()->v5.lock(*writeHandle, static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN),
1297 region, -1, (void**)&writeData));
1298
1299 uint8_t* readData;
1300 EXPECT_EQ(AIMAPPER_ERROR_NONE,
1301 mapper()->v5.lock(*readHandle, static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN),
1302 region, -1, (void**)&readData));
1303
1304 fillRGBA8888(writeData, info.height, stride * 4, info.width * 4);
1305
1306 EXPECT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.flushLockedBuffer(*writeHandle));
1307 EXPECT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.rereadLockedBuffer(*readHandle));
1308
1309 ASSERT_NO_FATAL_FAILURE(
1310 verifyRGBA8888(*readHandle, readData, info.height, stride * 4, info.width * 4));
1311
1312 int releaseFence = -1;
1313
1314 EXPECT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*readHandle, &releaseFence));
1315 if (releaseFence != -1) {
1316 close(releaseFence);
1317 releaseFence = -1;
1318 }
1319
1320 EXPECT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*writeHandle, &releaseFence));
1321 if (releaseFence != -1) {
1322 close(releaseFence);
1323 releaseFence = -1;
1324 }
1325 }
1326
TEST_P(GraphicsMapperStableCTests,FlushLockedBufferBadBuffer)1327 TEST_P(GraphicsMapperStableCTests, FlushLockedBufferBadBuffer) {
1328 // Amazingly this is enough to make the compiler happy even though flushLockedBuffer
1329 // is _Nonnull :shrug:
1330 buffer_handle_t badBuffer = nullptr;
1331 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.flushLockedBuffer(badBuffer));
1332 }
1333
TEST_P(GraphicsMapperStableCTests,RereadLockedBufferBadBuffer)1334 TEST_P(GraphicsMapperStableCTests, RereadLockedBufferBadBuffer) {
1335 buffer_handle_t badBuffer = nullptr;
1336 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.rereadLockedBuffer(badBuffer));
1337 }
1338
TEST_P(GraphicsMapperStableCTests,GetBufferId)1339 TEST_P(GraphicsMapperStableCTests, GetBufferId) {
1340 auto buffer = allocateGeneric();
1341 auto bufferHandle = buffer->import();
1342 auto bufferId = getStandardMetadata<StandardMetadataType::BUFFER_ID>(*bufferHandle);
1343 ASSERT_TRUE(bufferId.has_value());
1344
1345 auto buffer2 = allocateGeneric();
1346 auto bufferHandle2 = buffer2->import();
1347 auto bufferId2 = getStandardMetadata<StandardMetadataType::BUFFER_ID>(*bufferHandle2);
1348 ASSERT_TRUE(bufferId2.has_value());
1349
1350 EXPECT_NE(*bufferId, *bufferId2);
1351 }
1352
TEST_P(GraphicsMapperStableCTests,GetName)1353 TEST_P(GraphicsMapperStableCTests, GetName) {
1354 auto buffer = allocate({
1355 .name = {"Hello, World!"},
1356 .width = 64,
1357 .height = 64,
1358 .layerCount = 1,
1359 .format = PixelFormat::RGBA_8888,
1360 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
1361 .reservedSize = 0,
1362 });
1363 auto bufferHandle = buffer->import();
1364 auto name = getStandardMetadata<StandardMetadataType::NAME>(*bufferHandle);
1365 ASSERT_TRUE(name.has_value());
1366 EXPECT_EQ(*name, "Hello, World!");
1367 }
1368
TEST_P(GraphicsMapperStableCTests,GetWidthHeight)1369 TEST_P(GraphicsMapperStableCTests, GetWidthHeight) {
1370 auto buffer = allocate({
1371 .name = {"Hello, World!"},
1372 .width = 64,
1373 .height = 128,
1374 .layerCount = 1,
1375 .format = PixelFormat::RGBA_8888,
1376 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
1377 .reservedSize = 0,
1378 });
1379 auto bufferHandle = buffer->import();
1380 auto value = getStandardMetadata<StandardMetadataType::WIDTH>(*bufferHandle);
1381 ASSERT_TRUE(value.has_value());
1382 EXPECT_EQ(*value, 64);
1383 value = getStandardMetadata<StandardMetadataType::HEIGHT>(*bufferHandle);
1384 ASSERT_TRUE(value.has_value());
1385 EXPECT_EQ(*value, 128);
1386 }
1387
TEST_P(GraphicsMapperStableCTests,GetLayerCount)1388 TEST_P(GraphicsMapperStableCTests, GetLayerCount) {
1389 auto buffer = allocateGeneric();
1390 auto bufferHandle = buffer->import();
1391 auto value = getStandardMetadata<StandardMetadataType::LAYER_COUNT>(*bufferHandle);
1392 ASSERT_TRUE(value.has_value());
1393 EXPECT_EQ(*value, buffer->info().layerCount);
1394 }
1395
TEST_P(GraphicsMapperStableCTests,GetPixelFormatRequested)1396 TEST_P(GraphicsMapperStableCTests, GetPixelFormatRequested) {
1397 auto buffer = allocateGeneric();
1398 auto bufferHandle = buffer->import();
1399 auto value = getStandardMetadata<StandardMetadataType::PIXEL_FORMAT_REQUESTED>(*bufferHandle);
1400 ASSERT_TRUE(value.has_value());
1401 EXPECT_EQ(*value, buffer->info().format);
1402 }
1403
TEST_P(GraphicsMapperStableCTests,GetPixelFormatFourCC)1404 TEST_P(GraphicsMapperStableCTests, GetPixelFormatFourCC) {
1405 auto buffer = allocate({
1406 .name = {"Hello, World!"},
1407 .width = 64,
1408 .height = 128,
1409 .layerCount = 1,
1410 .format = PixelFormat::RGBA_8888,
1411 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
1412 .reservedSize = 0,
1413 });
1414 {
1415 auto bufferHandle = buffer->import();
1416 auto value = getStandardMetadata<StandardMetadataType::PIXEL_FORMAT_FOURCC>(*bufferHandle);
1417 ASSERT_TRUE(value.has_value());
1418 EXPECT_EQ(*value, DRM_FORMAT_ABGR8888);
1419 }
1420
1421 buffer = allocate({
1422 .name = {"yv12"},
1423 .width = 64,
1424 .height = 128,
1425 .layerCount = 1,
1426 .format = PixelFormat::YV12,
1427 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
1428 .reservedSize = 0,
1429 });
1430 {
1431 auto bufferHandle = buffer->import();
1432 auto value = getStandardMetadata<StandardMetadataType::PIXEL_FORMAT_FOURCC>(*bufferHandle);
1433 ASSERT_TRUE(value.has_value());
1434 EXPECT_EQ(*value, DRM_FORMAT_YVU420);
1435 }
1436 }
1437
TEST_P(GraphicsMapperStableCTests,GetPixelFormatModifier)1438 TEST_P(GraphicsMapperStableCTests, GetPixelFormatModifier) {
1439 auto buffer = allocateGeneric();
1440 auto bufferHandle = buffer->import();
1441 auto value = getStandardMetadata<StandardMetadataType::PIXEL_FORMAT_MODIFIER>(*bufferHandle);
1442 ASSERT_TRUE(value.has_value());
1443 // Only the upper 8-bits are defined and is just the vendor ID, the lower 56 bits are
1444 // then vendor specific. So there's not anything useful to assert here beyond just that
1445 // we successfully queried a value
1446 }
1447
TEST_P(GraphicsMapperStableCTests,GetUsage)1448 TEST_P(GraphicsMapperStableCTests, GetUsage) {
1449 auto buffer = allocateGeneric();
1450 auto bufferHandle = buffer->import();
1451 auto value = getStandardMetadata<StandardMetadataType::USAGE>(*bufferHandle);
1452 ASSERT_TRUE(value.has_value());
1453 EXPECT_EQ(buffer->info().usage, *value);
1454 }
1455
TEST_P(GraphicsMapperStableCTests,GetUsage64)1456 TEST_P(GraphicsMapperStableCTests, GetUsage64) {
1457 BufferDescriptorInfo info{
1458 .name = {"VTS_TEMP"},
1459 .width = 64,
1460 .height = 64,
1461 .layerCount = 1,
1462 .format = PixelFormat::RGBA_8888,
1463 .usage = BufferUsage::FRONT_BUFFER | BufferUsage::GPU_RENDER_TARGET |
1464 BufferUsage::COMPOSER_OVERLAY | BufferUsage::GPU_TEXTURE,
1465 .reservedSize = 0,
1466 };
1467 if (!isSupported(info)) {
1468 GTEST_SKIP();
1469 }
1470 auto buffer = allocate(info);
1471 auto bufferHandle = buffer->import();
1472 auto value = getStandardMetadata<StandardMetadataType::USAGE>(*bufferHandle);
1473 ASSERT_TRUE(value.has_value());
1474 using T = std::underlying_type_t<BufferUsage>;
1475 EXPECT_EQ(static_cast<T>(buffer->info().usage), static_cast<T>(*value));
1476 }
1477
TEST_P(GraphicsMapperStableCTests,GetAllocationSize)1478 TEST_P(GraphicsMapperStableCTests, GetAllocationSize) {
1479 auto buffer = allocateGeneric();
1480 auto bufferHandle = buffer->import();
1481 auto value = getStandardMetadata<StandardMetadataType::ALLOCATION_SIZE>(*bufferHandle);
1482 ASSERT_TRUE(value.has_value());
1483 const auto estimatedSize = buffer->stride() * buffer->info().height * 4;
1484 // This buffer has CPU usage, so we expect at least stride * height * 4 since it should be
1485 // generally linear uncompressed.
1486 EXPECT_GE(*value, estimatedSize)
1487 << "Expected allocation size to be at least stride * height * 4bpp";
1488 // Might need refining, but hopefully this a generous-enough upper-bound?
1489 EXPECT_LT(*value, estimatedSize * 2)
1490 << "Expected allocation size to less than double stride * height * 4bpp";
1491 }
1492
TEST_P(GraphicsMapperStableCTests,GetProtectedContent)1493 TEST_P(GraphicsMapperStableCTests, GetProtectedContent) {
1494 const BufferDescriptorInfo info{
1495 .name = {"prot8888"},
1496 .width = 64,
1497 .height = 64,
1498 .layerCount = 1,
1499 .format = PixelFormat::RGBA_8888,
1500 .usage = BufferUsage::PROTECTED | BufferUsage::COMPOSER_OVERLAY,
1501 .reservedSize = 0,
1502 };
1503 auto buffer = allocate(info);
1504 if (!buffer) {
1505 ASSERT_FALSE(isSupported(info))
1506 << "Allocation of trivial sized buffer failed, so isSupported() must be false";
1507 GTEST_SUCCEED() << "PROTECTED RGBA_8888 is unsupported";
1508 return;
1509 }
1510 auto bufferHandle = buffer->import();
1511 auto value = getStandardMetadata<StandardMetadataType::PROTECTED_CONTENT>(*bufferHandle);
1512 ASSERT_TRUE(value.has_value());
1513 EXPECT_EQ(*value, 1);
1514 }
1515
TEST_P(GraphicsMapperStableCTests,GetCompression)1516 TEST_P(GraphicsMapperStableCTests, GetCompression) {
1517 auto buffer = allocateGeneric();
1518 ASSERT_TRUE(buffer);
1519 auto bufferHandle = buffer->import();
1520 ASSERT_TRUE(bufferHandle);
1521 auto value = getStandardMetadata<StandardMetadataType::COMPRESSION>(*bufferHandle);
1522 ASSERT_TRUE(value.has_value());
1523 EXPECT_EQ(gralloc4::Compression_None.name, value->name);
1524 EXPECT_EQ(gralloc4::Compression_None.value, value->value);
1525 }
1526
TEST_P(GraphicsMapperStableCTests,GetInterlaced)1527 TEST_P(GraphicsMapperStableCTests, GetInterlaced) {
1528 auto buffer = allocateGeneric();
1529 ASSERT_TRUE(buffer);
1530 auto bufferHandle = buffer->import();
1531 ASSERT_TRUE(bufferHandle);
1532 auto value = getStandardMetadata<StandardMetadataType::INTERLACED>(*bufferHandle);
1533 ASSERT_TRUE(value.has_value());
1534 EXPECT_EQ(gralloc4::Interlaced_None.name, value->name);
1535 EXPECT_EQ(gralloc4::Interlaced_None.value, value->value);
1536 }
1537
TEST_P(GraphicsMapperStableCTests,GetChromaSiting)1538 TEST_P(GraphicsMapperStableCTests, GetChromaSiting) {
1539 auto buffer = allocateGeneric();
1540 ASSERT_TRUE(buffer);
1541 auto bufferHandle = buffer->import();
1542 ASSERT_TRUE(bufferHandle);
1543 auto value = getStandardMetadata<StandardMetadataType::CHROMA_SITING>(*bufferHandle);
1544 ASSERT_TRUE(value.has_value());
1545 EXPECT_EQ(gralloc4::ChromaSiting_None.name, value->name);
1546 EXPECT_EQ(gralloc4::ChromaSiting_None.value, value->value);
1547 }
1548
TEST_P(GraphicsMapperStableCTests,GetPlaneLayouts)1549 TEST_P(GraphicsMapperStableCTests, GetPlaneLayouts) {
1550 auto buffer = allocateGeneric();
1551 ASSERT_TRUE(buffer);
1552 auto bufferHandle = buffer->import();
1553 ASSERT_TRUE(bufferHandle);
1554 auto value = getStandardMetadata<StandardMetadataType::PLANE_LAYOUTS>(*bufferHandle);
1555 ASSERT_TRUE(value.has_value());
1556 ASSERT_NO_FATAL_FAILURE(verifyRGBA8888PlaneLayouts(*value));
1557 }
1558
TEST_P(GraphicsMapperStableCTests,GetCrop)1559 TEST_P(GraphicsMapperStableCTests, GetCrop) {
1560 auto buffer = allocateGeneric();
1561 ASSERT_TRUE(buffer);
1562 auto bufferHandle = buffer->import();
1563 ASSERT_TRUE(bufferHandle);
1564 auto value = getStandardMetadata<StandardMetadataType::CROP>(*bufferHandle);
1565 ASSERT_TRUE(value.has_value());
1566 EXPECT_EQ(1, value->size());
1567 const Rect expected{0, 0, buffer->info().width, buffer->info().height};
1568 EXPECT_EQ(expected, value->at(0));
1569 }
1570
TEST_P(GraphicsMapperStableCTests,GetSetDataspace)1571 TEST_P(GraphicsMapperStableCTests, GetSetDataspace) {
1572 auto buffer = allocateGeneric();
1573 ASSERT_TRUE(buffer);
1574 auto bufferHandle = buffer->import();
1575 ASSERT_TRUE(bufferHandle);
1576 auto value = getStandardMetadata<StandardMetadataType::DATASPACE>(*bufferHandle);
1577 ASSERT_TRUE(value.has_value());
1578 EXPECT_EQ(Dataspace::UNKNOWN, *value);
1579 EXPECT_EQ(AIMAPPER_ERROR_NONE, setStandardMetadata<StandardMetadataType::DATASPACE>(
1580 *bufferHandle, Dataspace::DISPLAY_P3));
1581 value = getStandardMetadata<StandardMetadataType::DATASPACE>(*bufferHandle);
1582 ASSERT_TRUE(value.has_value());
1583 EXPECT_EQ(Dataspace::DISPLAY_P3, *value);
1584 }
1585
TEST_P(GraphicsMapperStableCTests,GetSetBlendMode)1586 TEST_P(GraphicsMapperStableCTests, GetSetBlendMode) {
1587 auto buffer = allocateGeneric();
1588 ASSERT_TRUE(buffer);
1589 auto bufferHandle = buffer->import();
1590 ASSERT_TRUE(bufferHandle);
1591 auto value = getStandardMetadata<StandardMetadataType::BLEND_MODE>(*bufferHandle);
1592 ASSERT_TRUE(value.has_value());
1593 EXPECT_EQ(BlendMode::INVALID, *value);
1594 EXPECT_EQ(AIMAPPER_ERROR_NONE, setStandardMetadata<StandardMetadataType::BLEND_MODE>(
1595 *bufferHandle, BlendMode::COVERAGE));
1596 value = getStandardMetadata<StandardMetadataType::BLEND_MODE>(*bufferHandle);
1597 ASSERT_TRUE(value.has_value());
1598 EXPECT_EQ(BlendMode::COVERAGE, *value);
1599 }
1600
TEST_P(GraphicsMapperStableCTests,GetSetSmpte2086)1601 TEST_P(GraphicsMapperStableCTests, GetSetSmpte2086) {
1602 auto buffer = allocateGeneric();
1603 ASSERT_TRUE(buffer);
1604 auto bufferHandle = buffer->import();
1605 ASSERT_TRUE(bufferHandle);
1606 auto value = getStandardMetadata<StandardMetadataType::SMPTE2086>(*bufferHandle);
1607 ASSERT_TRUE(value.has_value());
1608 EXPECT_FALSE(value->has_value());
1609
1610 // TODO: Maybe use something resembling real values, but validation isn't supposed to happen
1611 // here anyway so :shrug:
1612 const Smpte2086 awesomeHdr{
1613 XyColor{1.f, 1.f}, XyColor{2.f, 2.f}, XyColor{3.f, 3.f},
1614 XyColor{400.f, 1000.f}, 100000.0f, 0.0001f,
1615 };
1616 EXPECT_EQ(AIMAPPER_ERROR_NONE,
1617 setStandardMetadata<StandardMetadataType::SMPTE2086>(*bufferHandle, awesomeHdr));
1618 value = getStandardMetadata<StandardMetadataType::SMPTE2086>(*bufferHandle);
1619 ASSERT_TRUE(value.has_value());
1620 ASSERT_TRUE(value->has_value());
1621 EXPECT_EQ(awesomeHdr, *value);
1622
1623 EXPECT_EQ(AIMAPPER_ERROR_NONE,
1624 setStandardMetadata<StandardMetadataType::SMPTE2086>(*bufferHandle, std::nullopt));
1625 value = getStandardMetadata<StandardMetadataType::SMPTE2086>(*bufferHandle);
1626 ASSERT_TRUE(value.has_value());
1627 EXPECT_FALSE(value->has_value());
1628 }
1629
TEST_P(GraphicsMapperStableCTests,GetCta861_3)1630 TEST_P(GraphicsMapperStableCTests, GetCta861_3) {
1631 auto buffer = allocateGeneric();
1632 ASSERT_TRUE(buffer);
1633 auto bufferHandle = buffer->import();
1634 ASSERT_TRUE(bufferHandle);
1635 auto value = getStandardMetadata<StandardMetadataType::CTA861_3>(*bufferHandle);
1636 ASSERT_TRUE(value.has_value());
1637 EXPECT_FALSE(value->has_value());
1638
1639 const Cta861_3 genericHlgish{1000.f, 140.f};
1640 EXPECT_EQ(AIMAPPER_ERROR_NONE,
1641 setStandardMetadata<StandardMetadataType::CTA861_3>(*bufferHandle, genericHlgish));
1642 value = getStandardMetadata<StandardMetadataType::CTA861_3>(*bufferHandle);
1643 ASSERT_TRUE(value.has_value());
1644 ASSERT_TRUE(value->has_value());
1645 EXPECT_EQ(genericHlgish, *value);
1646
1647 EXPECT_EQ(AIMAPPER_ERROR_NONE,
1648 setStandardMetadata<StandardMetadataType::CTA861_3>(*bufferHandle, std::nullopt));
1649 value = getStandardMetadata<StandardMetadataType::CTA861_3>(*bufferHandle);
1650 ASSERT_TRUE(value.has_value());
1651 EXPECT_FALSE(value->has_value());
1652 }
1653
TEST_P(GraphicsMapperStableCTests,GetSmpte2094_10)1654 TEST_P(GraphicsMapperStableCTests, GetSmpte2094_10) {
1655 auto buffer = allocateGeneric();
1656 ASSERT_TRUE(buffer);
1657 auto bufferHandle = buffer->import();
1658 ASSERT_TRUE(bufferHandle);
1659 auto value = getStandardMetadata<StandardMetadataType::SMPTE2094_10>(*bufferHandle);
1660 if (value.has_value()) {
1661 EXPECT_FALSE(value->has_value());
1662 }
1663 }
1664
TEST_P(GraphicsMapperStableCTests,GetSmpte2094_40)1665 TEST_P(GraphicsMapperStableCTests, GetSmpte2094_40) {
1666 auto buffer = allocateGeneric();
1667 ASSERT_TRUE(buffer);
1668 auto bufferHandle = buffer->import();
1669 ASSERT_TRUE(bufferHandle);
1670 auto value = getStandardMetadata<StandardMetadataType::SMPTE2094_40>(*bufferHandle);
1671 if (value.has_value()) {
1672 EXPECT_FALSE(value->has_value());
1673 }
1674 }
1675
TEST_P(GraphicsMapperStableCTests,GetStride)1676 TEST_P(GraphicsMapperStableCTests, GetStride) {
1677 auto buffer = allocateGeneric();
1678 ASSERT_TRUE(buffer);
1679 auto bufferHandle = buffer->import();
1680 ASSERT_TRUE(bufferHandle);
1681 auto value = getStandardMetadata<StandardMetadataType::STRIDE>(*bufferHandle);
1682 ASSERT_TRUE(value.has_value());
1683 EXPECT_EQ(buffer->stride(), *value);
1684 }
1685
TEST_P(GraphicsMapperStableCTests,SupportsRequiredGettersSetters)1686 TEST_P(GraphicsMapperStableCTests, SupportsRequiredGettersSetters) {
1687 auto buffer = allocateGeneric();
1688 ASSERT_TRUE(buffer);
1689 auto bufferHandle = buffer->import();
1690 ASSERT_TRUE(bufferHandle);
1691 const AIMapper_MetadataTypeDescription* descriptions = nullptr;
1692 size_t descriptionCount = 0;
1693 ASSERT_EQ(AIMAPPER_ERROR_NONE,
1694 mapper()->v5.listSupportedMetadataTypes(&descriptions, &descriptionCount));
1695 std::vector<StandardMetadataType> requiredGetters = {
1696 StandardMetadataType::BUFFER_ID,
1697 StandardMetadataType::NAME,
1698 StandardMetadataType::WIDTH,
1699 StandardMetadataType::HEIGHT,
1700 StandardMetadataType::LAYER_COUNT,
1701 StandardMetadataType::PIXEL_FORMAT_REQUESTED,
1702 StandardMetadataType::PIXEL_FORMAT_FOURCC,
1703 StandardMetadataType::PIXEL_FORMAT_MODIFIER,
1704 StandardMetadataType::USAGE,
1705 StandardMetadataType::ALLOCATION_SIZE,
1706 StandardMetadataType::PROTECTED_CONTENT,
1707 StandardMetadataType::COMPRESSION,
1708 StandardMetadataType::INTERLACED,
1709 StandardMetadataType::CHROMA_SITING,
1710 StandardMetadataType::PLANE_LAYOUTS,
1711 StandardMetadataType::CROP,
1712 StandardMetadataType::DATASPACE,
1713 StandardMetadataType::BLEND_MODE,
1714 StandardMetadataType::SMPTE2086,
1715 StandardMetadataType::CTA861_3,
1716 StandardMetadataType::STRIDE,
1717 };
1718
1719 std::vector<StandardMetadataType> requiredSetters = {
1720 StandardMetadataType::DATASPACE,
1721 StandardMetadataType::BLEND_MODE,
1722 StandardMetadataType::SMPTE2086,
1723 StandardMetadataType::CTA861_3,
1724 };
1725
1726 for (int i = 0; i < descriptionCount; i++) {
1727 const auto& it = descriptions[i];
1728 if (isStandardMetadata(it.metadataType)) {
1729 EXPECT_GT(it.metadataType.value, static_cast<int64_t>(StandardMetadataType::INVALID));
1730 EXPECT_LT(it.metadataType.value,
1731 ndk::internal::enum_values<StandardMetadataType>.size());
1732
1733 if (it.isGettable) {
1734 std::erase(requiredGetters,
1735 static_cast<StandardMetadataType>(it.metadataType.value));
1736 }
1737 if (it.isSettable) {
1738 std::erase(requiredSetters,
1739 static_cast<StandardMetadataType>(it.metadataType.value));
1740 }
1741 } else {
1742 EXPECT_NE(nullptr, it.description) << "Non-standard metadata must have a description";
1743 int len = strlen(it.description);
1744 EXPECT_GE(len, 0) << "Non-standard metadata must have a description";
1745 }
1746 }
1747
1748 EXPECT_EQ(0, requiredGetters.size()) << "Missing required getters" << toString(requiredGetters);
1749 EXPECT_EQ(0, requiredSetters.size()) << "Missing required setters" << toString(requiredSetters);
1750 }
1751
1752 /*
1753 * Test that verifies that if the optional StandardMetadataTypes have getters, they have
1754 * the required setters as well
1755 */
TEST_P(GraphicsMapperStableCTests,CheckRequiredSettersIfHasGetters)1756 TEST_P(GraphicsMapperStableCTests, CheckRequiredSettersIfHasGetters) {
1757 auto buffer = allocateGeneric();
1758 ASSERT_TRUE(buffer);
1759 auto bufferHandle = buffer->import();
1760 ASSERT_TRUE(bufferHandle);
1761 const AIMapper_MetadataTypeDescription* descriptions = nullptr;
1762 size_t descriptionCount = 0;
1763 ASSERT_EQ(AIMAPPER_ERROR_NONE,
1764 mapper()->v5.listSupportedMetadataTypes(&descriptions, &descriptionCount));
1765
1766 for (int i = 0; i < descriptionCount; i++) {
1767 const auto& it = descriptions[i];
1768 if (isStandardMetadata(it.metadataType)) {
1769 const auto type = static_cast<StandardMetadataType>(it.metadataType.value);
1770 switch (type) {
1771 case StandardMetadataType::SMPTE2094_10:
1772 case StandardMetadataType::SMPTE2094_40:
1773 if (it.isGettable) {
1774 EXPECT_TRUE(it.isSettable)
1775 << "Type " << toString(type) << " must be settable if gettable";
1776 }
1777 break;
1778 default:
1779 break;
1780 }
1781 }
1782 }
1783 }
1784
TEST_P(GraphicsMapperStableCTests,ListSupportedWorks)1785 TEST_P(GraphicsMapperStableCTests, ListSupportedWorks) {
1786 auto buffer = allocateGeneric();
1787 ASSERT_TRUE(buffer);
1788 auto bufferHandle = buffer->import();
1789 ASSERT_TRUE(bufferHandle);
1790 const AIMapper_MetadataTypeDescription* descriptions = nullptr;
1791 size_t descriptionCount = 0;
1792 ASSERT_EQ(AIMAPPER_ERROR_NONE,
1793 mapper()->v5.listSupportedMetadataTypes(&descriptions, &descriptionCount));
1794
1795 std::vector<uint8_t> metadataBuffer;
1796 auto get = [&](AIMapper_MetadataType metadataType) -> int32_t {
1797 int32_t size = mapper()->v5.getMetadata(*bufferHandle, metadataType, nullptr, 0);
1798 if (size >= 0) {
1799 metadataBuffer.resize(size);
1800 size = mapper()->v5.getMetadata(*bufferHandle, metadataType, metadataBuffer.data(),
1801 metadataBuffer.size());
1802 EXPECT_EQ(size, metadataBuffer.size());
1803 }
1804 return size;
1805 };
1806
1807 for (int i = 0; i < descriptionCount; i++) {
1808 const auto& it = descriptions[i];
1809 if (!isStandardMetadata(it.metadataType)) {
1810 continue;
1811 }
1812 if (!it.isGettable) {
1813 EXPECT_FALSE(it.isSettable)
1814 << "StandardMetadata that isn't gettable must not be settable";
1815 continue;
1816 }
1817 EXPECT_GE(get(it.metadataType), 0)
1818 << "Get failed for claimed supported getter of "
1819 << toString(static_cast<StandardMetadataType>(it.metadataType.value));
1820 if (it.isSettable) {
1821 EXPECT_EQ(AIMAPPER_ERROR_NONE,
1822 mapper()->v5.setMetadata(*bufferHandle, it.metadataType,
1823 metadataBuffer.data(), metadataBuffer.size()))
1824 << "Failed to set metadata for "
1825 << toString(static_cast<StandardMetadataType>(it.metadataType.value));
1826 }
1827 }
1828 }
1829
TEST_P(GraphicsMapperStableCTests,GetMetadataBadValue)1830 TEST_P(GraphicsMapperStableCTests, GetMetadataBadValue) {
1831 auto get = [this](StandardMetadataType type) -> AIMapper_Error {
1832 // This is a _Nonnull parameter, but this is enough obfuscation to fool the linter
1833 buffer_handle_t buffer = nullptr;
1834 int32_t ret =
1835 mapper()->v5.getStandardMetadata(buffer, static_cast<int64_t>(type), nullptr, 0);
1836 return (ret < 0) ? (AIMapper_Error)-ret : AIMAPPER_ERROR_NONE;
1837 };
1838
1839 for (auto type : ndk::enum_range<StandardMetadataType>()) {
1840 if (type == StandardMetadataType::INVALID) {
1841 continue;
1842 }
1843 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, get(type)) << "Wrong error for " << toString(type);
1844 }
1845 }
1846
TEST_P(GraphicsMapperStableCTests,GetUnsupportedMetadata)1847 TEST_P(GraphicsMapperStableCTests, GetUnsupportedMetadata) {
1848 auto buffer = allocateGeneric();
1849 ASSERT_TRUE(buffer);
1850 auto bufferHandle = buffer->import();
1851 ASSERT_TRUE(bufferHandle);
1852
1853 int result = mapper()->v5.getMetadata(*bufferHandle, {"Fake", 1}, nullptr, 0);
1854 EXPECT_EQ(AIMAPPER_ERROR_UNSUPPORTED, -result);
1855
1856 result = mapper()->v5.getStandardMetadata(
1857 *bufferHandle, static_cast<int64_t>(StandardMetadataType::INVALID), nullptr, 0);
1858 EXPECT_EQ(AIMAPPER_ERROR_UNSUPPORTED, -result);
1859
1860 constexpr int64_t unknownStandardType = ndk::internal::enum_values<StandardMetadataType>.size();
1861 result = mapper()->v5.getStandardMetadata(*bufferHandle, unknownStandardType, nullptr, 0);
1862 EXPECT_EQ(AIMAPPER_ERROR_UNSUPPORTED, -result);
1863 }
1864
getIAllocatorsAtLeastVersion(int32_t minVersion)1865 std::vector<std::tuple<std::string, std::shared_ptr<IAllocator>>> getIAllocatorsAtLeastVersion(
1866 int32_t minVersion) {
1867 auto instanceNames = getAidlHalInstanceNames(IAllocator::descriptor);
1868 std::vector<std::tuple<std::string, std::shared_ptr<IAllocator>>> filteredInstances;
1869 filteredInstances.reserve(instanceNames.size());
1870 for (const auto& name : instanceNames) {
1871 auto allocator =
1872 IAllocator::fromBinder(ndk::SpAIBinder(AServiceManager_checkService(name.c_str())));
1873 int32_t version = 0;
1874 if (allocator->getInterfaceVersion(&version).isOk()) {
1875 if (version >= minVersion) {
1876 filteredInstances.emplace_back(name, std::move(allocator));
1877 }
1878 }
1879 }
1880 return filteredInstances;
1881 }
1882
1883 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsMapperStableCTests);
1884 INSTANTIATE_TEST_CASE_P(PerInstance, GraphicsMapperStableCTests,
1885 testing::ValuesIn(getIAllocatorsAtLeastVersion(2)),
__anonf29e99dc0502(auto info) 1886 [](auto info) -> std::string {
1887 std::string name =
1888 std::to_string(info.index) + "/" + std::get<0>(info.param);
1889 return Sanitize(name);
1890 });