diff --git a/graphics/composer/aidl/vts/ReadbackVts.cpp b/graphics/composer/aidl/vts/ReadbackVts.cpp index 283b8ce2e4..9d5928d896 100644 --- a/graphics/composer/aidl/vts/ReadbackVts.cpp +++ b/graphics/composer/aidl/vts/ReadbackVts.cpp @@ -16,6 +16,7 @@ #include "ReadbackVts.h" #include +#include #include "RenderEngineVts.h" #include "renderengine/ExternalTexture.h" #include "renderengine/impl/ExternalTexture.h" @@ -106,37 +107,72 @@ LayerSettings TestLayer::toRenderEngineLayerSettings() { return layerSettings; } -int32_t ReadbackHelper::GetBytesPerPixel(common::PixelFormat pixelFormat) { +int32_t ReadbackHelper::GetBitsPerChannel(common::PixelFormat pixelFormat) { switch (pixelFormat) { + case common::PixelFormat::RGBA_1010102: + return 10; case common::PixelFormat::RGBA_8888: - return 4; case common::PixelFormat::RGB_888: - return 3; + return 8; default: return -1; } } -void ReadbackHelper::fillBuffer(uint32_t width, uint32_t height, uint32_t stride, void* bufferData, +int32_t ReadbackHelper::GetAlphaBits(common::PixelFormat pixelFormat) { + switch (pixelFormat) { + case common::PixelFormat::RGBA_8888: + return 8; + case common::PixelFormat::RGBA_1010102: + return 2; + case common::PixelFormat::RGB_888: + return 0; + default: + return -1; + } +} + +void ReadbackHelper::fillBuffer(uint32_t width, uint32_t height, uint32_t stride, + int32_t bytesPerPixel, void* bufferData, common::PixelFormat pixelFormat, std::vector desiredPixelColors) { ASSERT_TRUE(pixelFormat == common::PixelFormat::RGB_888 || - pixelFormat == common::PixelFormat::RGBA_8888); - int32_t bytesPerPixel = GetBytesPerPixel(pixelFormat); + pixelFormat == common::PixelFormat::RGBA_8888 || + pixelFormat == common::PixelFormat::RGBA_1010102); + int32_t bitsPerChannel = GetBitsPerChannel(pixelFormat); + int32_t alphaBits = GetAlphaBits(pixelFormat); + ASSERT_NE(-1, alphaBits); + ASSERT_NE(-1, bitsPerChannel); ASSERT_NE(-1, bytesPerPixel); - for (int row = 0; row < height; row++) { - for (int col = 0; col < width; col++) { - auto pixel = row * static_cast(width) + col; + + uint32_t maxValue = (1 << bitsPerChannel) - 1; + uint32_t maxAlphaValue = (1 << alphaBits) - 1; + for (uint32_t row = 0; row < height; row++) { + for (uint32_t col = 0; col < width; col++) { + auto pixel = row * width + col; Color srcColor = desiredPixelColors[static_cast(pixel)]; - int offset = (row * static_cast(stride) + col) * bytesPerPixel; - uint8_t* pixelColor = (uint8_t*)bufferData + offset; - pixelColor[0] = static_cast(std::round(255.0f * srcColor.r)); - pixelColor[1] = static_cast(std::round(255.0f * srcColor.g)); - pixelColor[2] = static_cast(std::round(255.0f * srcColor.b)); + uint32_t offset = (row * stride + col) * static_cast(bytesPerPixel); - if (bytesPerPixel == 4) { - pixelColor[3] = static_cast(std::round(255.0f * srcColor.a)); + uint32_t* pixelStart = (uint32_t*)((uint8_t*)bufferData + offset); + + uint32_t red = static_cast(std::round(maxValue * srcColor.r)); + uint32_t green = static_cast(std::round(maxValue * srcColor.g)); + uint32_t blue = static_cast(std::round(maxValue * srcColor.b)); + + // Boo we're not word aligned so special case this. + if (pixelFormat == common::PixelFormat::RGB_888) { + uint8_t* pixelColor = (uint8_t*)pixelStart; + pixelColor[0] = static_cast(red); + pixelColor[1] = static_cast(green); + pixelColor[2] = static_cast(blue); + } else { + uint32_t alpha = static_cast(std::round(maxAlphaValue * srcColor.a)); + uint32_t color = (alpha << (32 - alphaBits)) | + (blue << (32 - alphaBits - bitsPerChannel)) | + (green << (32 - alphaBits - bitsPerChannel * 2)) | + (red << (32 - alphaBits - bitsPerChannel * 3)); + *pixelStart = color; } } } @@ -165,7 +201,8 @@ void ReadbackHelper::fillColorsArea(std::vector& expectedColors, int32_t bool ReadbackHelper::readbackSupported(const common::PixelFormat& pixelFormat, const common::Dataspace& dataspace) { if (pixelFormat != common::PixelFormat::RGB_888 && - pixelFormat != common::PixelFormat::RGBA_8888) { + pixelFormat != common::PixelFormat::RGBA_8888 && + pixelFormat != common::PixelFormat::RGBA_1010102) { return false; } if (std::find(dataspaces.begin(), dataspaces.end(), dataspace) == dataspaces.end()) { @@ -175,36 +212,110 @@ bool ReadbackHelper::readbackSupported(const common::PixelFormat& pixelFormat, } void ReadbackHelper::compareColorBuffers(const std::vector& expectedColors, void* bufferData, - const uint32_t stride, const uint32_t width, - const uint32_t height, common::PixelFormat pixelFormat) { - const int32_t bytesPerPixel = ReadbackHelper::GetBytesPerPixel(pixelFormat); - ASSERT_NE(-1, bytesPerPixel); - for (int row = 0; row < height; row++) { - for (int col = 0; col < width; col++) { - auto pixel = row * static_cast(width) + col; - int offset = (row * static_cast(stride) + col) * bytesPerPixel; - uint8_t* pixelColor = (uint8_t*)bufferData + offset; + const uint32_t stride, int32_t bytesPerPixel, + const uint32_t width, const uint32_t height, + common::PixelFormat pixelFormat) { + int32_t bitsPerChannel = GetBitsPerChannel(pixelFormat); + int32_t alphaBits = GetAlphaBits(pixelFormat); + ASSERT_GT(bytesPerPixel, 0); + ASSERT_NE(-1, alphaBits); + ASSERT_NE(-1, bitsPerChannel); + uint32_t maxValue = (1 << bitsPerChannel) - 1; + uint32_t maxAlphaValue = (1 << alphaBits) - 1; + for (uint32_t row = 0; row < height; row++) { + for (uint32_t col = 0; col < width; col++) { + auto pixel = row * width + col; const Color expectedColor = expectedColors[static_cast(pixel)]; - ASSERT_EQ(std::round(255.0f * expectedColor.r), pixelColor[0]); - ASSERT_EQ(std::round(255.0f * expectedColor.g), pixelColor[1]); - ASSERT_EQ(std::round(255.0f * expectedColor.b), pixelColor[2]); + + uint32_t offset = (row * stride + col) * static_cast(bytesPerPixel); + uint32_t* pixelStart = (uint32_t*)((uint8_t*)bufferData + offset); + + uint32_t expectedRed = static_cast(std::round(maxValue * expectedColor.r)); + uint32_t expectedGreen = static_cast(std::round(maxValue * expectedColor.g)); + uint32_t expectedBlue = static_cast(std::round(maxValue * expectedColor.b)); + + // Boo we're not word aligned so special case this. + if (pixelFormat == common::PixelFormat::RGB_888) { + uint8_t* pixelColor = (uint8_t*)pixelStart; + ASSERT_EQ(pixelColor[0], static_cast(expectedRed)) + << "Red channel mismatch at (" << row << ", " << col << ")"; + ASSERT_EQ(pixelColor[1], static_cast(expectedGreen)) + << "Green channel mismatch at (" << row << ", " << col << ")"; + ASSERT_EQ(pixelColor[2], static_cast(expectedBlue)) + << "Blue channel mismatch at (" << row << ", " << col << ")"; + } else { + uint32_t expectedAlpha = + static_cast(std::round(maxAlphaValue * expectedColor.a)); + + uint32_t actualRed = + (*pixelStart >> (32 - alphaBits - bitsPerChannel * 3)) & maxValue; + uint32_t actualGreen = + (*pixelStart >> (32 - alphaBits - bitsPerChannel * 2)) & maxValue; + uint32_t actualBlue = (*pixelStart >> (32 - alphaBits - bitsPerChannel)) & maxValue; + uint32_t actualAlpha = (*pixelStart >> (32 - alphaBits)) & maxAlphaValue; + + ASSERT_EQ(expectedRed, actualRed) + << "Red channel mismatch at (" << row << ", " << col << ")"; + ASSERT_EQ(expectedGreen, actualGreen) + << "Green channel mismatch at (" << row << ", " << col << ")"; + ASSERT_EQ(expectedBlue, actualBlue) + << "Blue channel mismatch at (" << row << ", " << col << ")"; + } } } } void ReadbackHelper::compareColorBuffers(void* expectedBuffer, void* actualBuffer, - const uint32_t stride, const uint32_t width, - const uint32_t height, common::PixelFormat pixelFormat) { - const int32_t bytesPerPixel = ReadbackHelper::GetBytesPerPixel(pixelFormat); - ASSERT_NE(-1, bytesPerPixel); - for (int row = 0; row < height; row++) { - for (int col = 0; col < width; col++) { - int offset = (row * static_cast(stride) + col) * bytesPerPixel; - uint8_t* expectedColor = (uint8_t*)expectedBuffer + offset; - uint8_t* actualColor = (uint8_t*)actualBuffer + offset; - ASSERT_EQ(expectedColor[0], actualColor[0]); - ASSERT_EQ(expectedColor[1], actualColor[1]); - ASSERT_EQ(expectedColor[2], actualColor[2]); + const uint32_t stride, int32_t bytesPerPixel, + const uint32_t width, const uint32_t height, + common::PixelFormat pixelFormat) { + int32_t bitsPerChannel = GetBitsPerChannel(pixelFormat); + int32_t alphaBits = GetAlphaBits(pixelFormat); + ASSERT_GT(bytesPerPixel, 0); + ASSERT_NE(-1, alphaBits); + ASSERT_NE(-1, bitsPerChannel); + uint32_t maxValue = (1 << bitsPerChannel) - 1; + uint32_t maxAlphaValue = (1 << alphaBits) - 1; + for (uint32_t row = 0; row < height; row++) { + for (uint32_t col = 0; col < width; col++) { + uint32_t offset = (row * stride + col) * static_cast(bytesPerPixel); + uint32_t* expectedStart = (uint32_t*)((uint8_t*)expectedBuffer + offset); + uint32_t* actualStart = (uint32_t*)((uint8_t*)actualBuffer + offset); + + // Boo we're not word aligned so special case this. + if (pixelFormat == common::PixelFormat::RGB_888) { + uint8_t* expectedPixel = (uint8_t*)expectedStart; + uint8_t* actualPixel = (uint8_t*)actualStart; + ASSERT_EQ(actualPixel[0], expectedPixel[0]) + << "Red channel mismatch at (" << row << ", " << col << ")"; + ASSERT_EQ(actualPixel[1], expectedPixel[1]) + << "Green channel mismatch at (" << row << ", " << col << ")"; + ASSERT_EQ(actualPixel[2], expectedPixel[2]) + << "Blue channel mismatch at (" << row << ", " << col << ")"; + } else { + uint32_t expectedRed = + (*expectedStart >> (32 - alphaBits - bitsPerChannel * 3)) & maxValue; + uint32_t expectedGreen = + (*expectedStart >> (32 - alphaBits - bitsPerChannel * 2)) & maxValue; + uint32_t expectedBlue = + (*expectedStart >> (32 - alphaBits - bitsPerChannel)) & maxValue; + uint32_t expectedAlpha = (*expectedStart >> (32 - alphaBits)) & maxAlphaValue; + + uint32_t actualRed = + (*actualStart >> (32 - alphaBits - bitsPerChannel * 3)) & maxValue; + uint32_t actualGreen = + (*actualStart >> (32 - alphaBits - bitsPerChannel * 2)) & maxValue; + uint32_t actualBlue = + (*actualStart >> (32 - alphaBits - bitsPerChannel)) & maxValue; + uint32_t actualAlpha = (*actualStart >> (32 - alphaBits)) & maxAlphaValue; + + ASSERT_EQ(expectedRed, actualRed) + << "Red channel mismatch at (" << row << ", " << col << ")"; + ASSERT_EQ(expectedGreen, actualGreen) + << "Green channel mismatch at (" << row << ", " << col << ")"; + ASSERT_EQ(expectedBlue, actualBlue) + << "Blue channel mismatch at (" << row << ", " << col << ")"; + } } } } @@ -258,12 +369,13 @@ void ReadbackBuffer::checkReadbackBuffer(const std::vector& expectedColor auto status = mGraphicBuffer->lockAsync(mUsage, mAccessRegion, &bufData, dup(bufferFence.get()), &bytesPerPixel, &bytesPerStride); EXPECT_EQ(::android::OK, status); - ASSERT_TRUE(mPixelFormat == PixelFormat::RGB_888 || mPixelFormat == PixelFormat::RGBA_8888); + ASSERT_TRUE(mPixelFormat == PixelFormat::RGB_888 || mPixelFormat == PixelFormat::RGBA_8888 || + mPixelFormat == PixelFormat::RGBA_1010102); const uint32_t stride = (bytesPerPixel > 0 && bytesPerStride > 0) ? static_cast(bytesPerStride / bytesPerPixel) : mGraphicBuffer->getStride(); - ReadbackHelper::compareColorBuffers(expectedColors, bufData, stride, mWidth, mHeight, - mPixelFormat); + ReadbackHelper::compareColorBuffers(expectedColors, bufData, stride, bytesPerPixel, mWidth, + mHeight, mPixelFormat); status = mGraphicBuffer->unlock(); EXPECT_EQ(::android::OK, status); } @@ -353,8 +465,8 @@ void TestBufferLayer::fillBuffer(std::vector& expectedColors) { ? static_cast(bytesPerStride / bytesPerPixel) : mGraphicBuffer->getStride(); EXPECT_EQ(::android::OK, status); - ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(mWidth, mHeight, stride, bufData, - mPixelFormat, expectedColors)); + ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(mWidth, mHeight, stride, bytesPerPixel, + bufData, mPixelFormat, expectedColors)); const auto unlockStatus = mGraphicBuffer->unlockAsync(&mFillFence); ASSERT_EQ(::android::OK, unlockStatus); diff --git a/graphics/composer/aidl/vts/ReadbackVts.h b/graphics/composer/aidl/vts/ReadbackVts.h index 8ac0f4bb99..e3b2384f5c 100644 --- a/graphics/composer/aidl/vts/ReadbackVts.h +++ b/graphics/composer/aidl/vts/ReadbackVts.h @@ -172,10 +172,12 @@ class ReadbackHelper { static Dataspace getDataspaceForColorMode(ColorMode mode); - static int32_t GetBytesPerPixel(PixelFormat pixelFormat); + static int32_t GetBitsPerChannel(PixelFormat pixelFormat); + static int32_t GetAlphaBits(PixelFormat pixelFormat); - static void fillBuffer(uint32_t width, uint32_t height, uint32_t stride, void* bufferData, - PixelFormat pixelFormat, std::vector desiredPixelColors); + static void fillBuffer(uint32_t width, uint32_t height, uint32_t stride, int32_t bytesPerPixel, + void* bufferData, PixelFormat pixelFormat, + std::vector desiredPixelColors); static void clearColors(std::vector& expectedColors, int32_t width, int32_t height, int32_t displayWidth); @@ -189,11 +191,12 @@ class ReadbackHelper { static const std::vector dataspaces; static void compareColorBuffers(const std::vector& expectedColors, void* bufferData, - const uint32_t stride, const uint32_t width, - const uint32_t height, PixelFormat pixelFormat); - static void compareColorBuffers(void* expectedBuffer, void* actualBuffer, const uint32_t stride, + const uint32_t stride, int32_t bytesPerPixel, const uint32_t width, const uint32_t height, PixelFormat pixelFormat); + static void compareColorBuffers(void* expectedBuffer, void* actualBuffer, const uint32_t stride, + int32_t bytesPerPixel, const uint32_t width, + const uint32_t height, PixelFormat pixelFormat); }; class ReadbackBuffer { diff --git a/graphics/composer/aidl/vts/RenderEngineVts.cpp b/graphics/composer/aidl/vts/RenderEngineVts.cpp index 4e7f7735ea..48cb8ae5a6 100644 --- a/graphics/composer/aidl/vts/RenderEngineVts.cpp +++ b/graphics/composer/aidl/vts/RenderEngineVts.cpp @@ -83,7 +83,7 @@ void TestRenderEngine::checkColorBuffer(const std::vector& expectedColors const uint32_t stride = (bytesPerPixel > 0 && bytesPerStride > 0) ? static_cast(bytesPerStride / bytesPerPixel) : mGraphicBuffer->getStride(); - ReadbackHelper::compareColorBuffers(expectedColors, bufferData, stride, + ReadbackHelper::compareColorBuffers(expectedColors, bufferData, stride, bytesPerPixel, mGraphicBuffer->getWidth(), mGraphicBuffer->getHeight(), mFormat); ASSERT_EQ(::android::OK, mGraphicBuffer->unlock()); @@ -110,7 +110,7 @@ void TestRenderEngine::checkColorBuffer(const ::android::sp<::android::GraphicBu ASSERT_EQ(renderedStride, bufferStride); - ReadbackHelper::compareColorBuffers(renderedBufferData, bufferData, bufferStride, + ReadbackHelper::compareColorBuffers(renderedBufferData, bufferData, bufferStride, bytesPerPixel, mGraphicBuffer->getWidth(), mGraphicBuffer->getHeight(), mFormat); ASSERT_EQ(::android::OK, buffer->unlock()); diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp index 3d9253f917..9db8794fd6 100644 --- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp +++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp @@ -496,11 +496,14 @@ TEST_P(GraphicsCompositionTest, ClientComposition) { const auto& buffer = graphicBuffer->handle; void* clientBufData; const auto stride = static_cast(graphicBuffer->stride); - graphicBuffer->lock(clientUsage, layer->getAccessRegion(), &clientBufData); + int bytesPerPixel = -1; + int bytesPerStride = -1; + graphicBuffer->lock(clientUsage, layer->getAccessRegion(), &clientBufData, + &bytesPerPixel, &bytesPerStride); - ASSERT_NO_FATAL_FAILURE( - ReadbackHelper::fillBuffer(layer->getWidth(), layer->getHeight(), stride, - clientBufData, clientFormat, expectedColors)); + ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer( + layer->getWidth(), layer->getHeight(), stride, bytesPerPixel, clientBufData, + clientFormat, expectedColors)); int32_t clientFence; const auto unlockStatus = graphicBuffer->unlockAsync(&clientFence); ASSERT_EQ(::android::OK, unlockStatus); @@ -677,15 +680,18 @@ TEST_P(GraphicsCompositionTest, DeviceAndClientComposition) { const auto& buffer = graphicBuffer->handle; void* clientBufData; + int bytesPerPixel = -1; + int bytesPerStride = -1; graphicBuffer->lock(clientUsage, {0, 0, getDisplayWidth(), getDisplayHeight()}, - &clientBufData); + &clientBufData, &bytesPerPixel, &bytesPerStride); std::vector clientColors( static_cast(getDisplayWidth() * getDisplayHeight())); ReadbackHelper::fillColorsArea(clientColors, getDisplayWidth(), clientFrame, RED); ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer( static_cast(getDisplayWidth()), static_cast(getDisplayHeight()), - graphicBuffer->getStride(), clientBufData, clientFormat, clientColors)); + graphicBuffer->getStride(), bytesPerPixel, clientBufData, clientFormat, + clientColors)); int32_t clientFence; const auto unlockStatus = graphicBuffer->unlockAsync(&clientFence); ASSERT_EQ(::android::OK, unlockStatus);