diff --git a/graphics/mapper/4.0/vts/functional/Android.bp b/graphics/mapper/4.0/vts/functional/Android.bp index 5a7548a4f8..a8030ab633 100644 --- a/graphics/mapper/4.0/vts/functional/Android.bp +++ b/graphics/mapper/4.0/vts/functional/Android.bp @@ -30,5 +30,8 @@ cc_test { "libgralloctypes", "vintf-graphics-common-ndk_platform", ], + header_libs: [ + "libsystem_headers", + ], test_suites: ["general-tests"], } diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp index 870e6eb058..d63b078d1b 100644 --- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp +++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp @@ -20,13 +20,13 @@ #include #include -//#include -//#include +#include #include #include #include #include +#include namespace android { namespace hardware { @@ -44,6 +44,7 @@ using aidl::android::hardware::graphics::common::Dataspace; using aidl::android::hardware::graphics::common::ExtendableType; using aidl::android::hardware::graphics::common::PlaneLayout; using aidl::android::hardware::graphics::common::PlaneLayoutComponent; +using aidl::android::hardware::graphics::common::PlaneLayoutComponentType; using aidl::android::hardware::graphics::common::StandardMetadataType; using DecodeFunction = std::function vec; + ASSERT_EQ(Error::NONE, + mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec)); + std::vector planeLayouts; + ASSERT_EQ(NO_ERROR, gralloc4::decodePlaneLayouts(vec, &planeLayouts)); + + outYCbCr->y = nullptr; + outYCbCr->cb = nullptr; + outYCbCr->cr = nullptr; + outYCbCr->ystride = 0; + outYCbCr->cstride = 0; + outYCbCr->chroma_step = 0; + + for (const auto& planeLayout : planeLayouts) { + for (const auto& planeLayoutComponent : planeLayout.components) { + std::string componentTypeName = planeLayoutComponent.type.name; + if (!std::strncmp(componentTypeName.c_str(), GRALLOC4_PLANE_LAYOUT_COMPONENT_TYPE, + componentTypeName.size())) { + continue; + } + ASSERT_EQ(0, planeLayoutComponent.offsetInBits % 8); + + uint8_t* tmpData = + data + planeLayout.offsetInBytes + (planeLayoutComponent.offsetInBits / 8); + uint64_t sampleIncrementInBytes; + + auto type = static_cast(planeLayoutComponent.type.value); + switch (type) { + case PlaneLayoutComponentType::Y: + ASSERT_EQ(nullptr, outYCbCr->y); + ASSERT_EQ(8, planeLayoutComponent.sizeInBits); + ASSERT_EQ(8, planeLayout.sampleIncrementInBits); + outYCbCr->y = tmpData; + outYCbCr->ystride = planeLayout.strideInBytes; + break; + + case PlaneLayoutComponentType::CB: + case PlaneLayoutComponentType::CR: + ASSERT_EQ(0, planeLayout.sampleIncrementInBits % 8); + + sampleIncrementInBytes = planeLayout.sampleIncrementInBits / 8; + ASSERT_TRUE(sampleIncrementInBytes == 1 || sampleIncrementInBytes == 2); + + if (outYCbCr->cstride == 0 && outYCbCr->chroma_step == 0) { + outYCbCr->cstride = planeLayout.strideInBytes; + outYCbCr->chroma_step = sampleIncrementInBytes; + } else { + ASSERT_EQ(outYCbCr->cstride, planeLayout.strideInBytes); + ASSERT_EQ(outYCbCr->chroma_step, sampleIncrementInBytes); + } + + if (type == PlaneLayoutComponentType::CB) { + ASSERT_EQ(nullptr, outYCbCr->cb); + outYCbCr->cb = tmpData; + } else { + ASSERT_EQ(nullptr, outYCbCr->cr); + outYCbCr->cr = tmpData; + } + break; + default: + break; + }; + } + } + + ASSERT_NE(nullptr, outYCbCr->y); + ASSERT_NE(nullptr, outYCbCr->cb); + ASSERT_NE(nullptr, outYCbCr->cr); + } + std::unique_ptr mGralloc; IMapper::BufferDescriptorInfo mDummyDescriptorInfo{}; static const std::set sRequiredMetadataTypes; @@ -482,6 +555,76 @@ TEST_F(GraphicsMapperHidlTest, LockUnlockBasic) { } } +TEST_F(GraphicsMapperHidlTest, Lock_YCBCR_420_888) { + auto info = mDummyDescriptorInfo; + info.format = PixelFormat::YCBCR_420_888; + + const native_handle_t* bufferHandle; + uint32_t stride; + ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true, false, &stride)); + + // lock buffer for writing + const IMapper::Rect region{0, 0, static_cast(info.width), + static_cast(info.height)}; + int fence = -1; + uint8_t* data; + + ASSERT_NO_FATAL_FAILURE( + data = static_cast(mGralloc->lock(bufferHandle, info.usage, region, fence))); + + android_ycbcr yCbCr; + ASSERT_NO_FATAL_FAILURE(getAndroidYCbCr(bufferHandle, data, &yCbCr)); + + auto yData = static_cast(yCbCr.y); + auto cbData = static_cast(yCbCr.cb); + auto crData = static_cast(yCbCr.cr); + auto yStride = yCbCr.ystride; + auto cStride = yCbCr.cstride; + auto chromaStep = yCbCr.chroma_step; + + for (uint32_t y = 0; y < info.height; y++) { + for (uint32_t x = 0; x < info.width; x++) { + auto val = static_cast(info.height * y + x); + + yData[yStride * y + x] = val; + + if (y % chromaStep && x % chromaStep == 0) { + cbData[cStride * y / chromaStep + x / chromaStep] = val; + crData[cStride * y / chromaStep + x / chromaStep] = val; + } + } + } + + ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle)); + + // lock again for reading + ASSERT_NO_FATAL_FAILURE( + data = static_cast(mGralloc->lock(bufferHandle, info.usage, region, fence))); + + ASSERT_NO_FATAL_FAILURE(getAndroidYCbCr(bufferHandle, data, &yCbCr)); + + yData = static_cast(yCbCr.y); + cbData = static_cast(yCbCr.cb); + crData = static_cast(yCbCr.cr); + for (uint32_t y = 0; y < info.height; y++) { + for (uint32_t x = 0; x < info.width; x++) { + auto val = static_cast(info.height * y + x); + + EXPECT_EQ(val, yData[yStride * y + x]); + + if (y % chromaStep == 0 && x % chromaStep == 0) { + EXPECT_EQ(val, cbData[cStride * y / chromaStep + x / chromaStep]); + EXPECT_EQ(val, crData[cStride * y / chromaStep + x / chromaStep]); + } + } + } + + ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle)); + if (fence >= 0) { + close(fence); + } +} + /** * Test IMapper::unlock with bad access region */