From cfb29a4e7b4905522f7e5dc9a546c7449de2f91c Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Wed, 8 Aug 2018 09:39:53 -0700 Subject: [PATCH] Adding more Readback tests and refactoring Bug: 111563608 Test: ./VtsHalGraphicsComposerV2_2TargetTest --gtest_filter=GraphicsComposerReadbackTest.* Change-Id: I0e4a8212bf08c2890747f99d5754f92821c2e2f4 --- ...VtsHalGraphicsComposerV2_2ReadbackTest.cpp | 1305 +++++++++++++++-- 1 file changed, 1147 insertions(+), 158 deletions(-) diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp index 91318bc532..db4c914bbe 100644 --- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp +++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp @@ -44,6 +44,12 @@ using V2_1::Display; using V2_1::Layer; using V2_1::vts::TestCommandReader; +static const IComposerClient::Color BLACK = {0, 0, 0, 0xff}; +static const IComposerClient::Color RED = {0xff, 0, 0, 0xff}; +static const IComposerClient::Color TRANSLUCENT_RED = {0xff, 0, 0, 0x33}; +static const IComposerClient::Color GREEN = {0, 0xff, 0, 0xff}; +static const IComposerClient::Color BLUE = {0, 0, 0xff, 0xff}; + // Test environment for graphics.composer class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { public: @@ -61,106 +67,57 @@ class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEn class TestLayer { public: - TestLayer(std::shared_ptr const client, Display display) - : mLayer(client->createLayer(display, kBufferSlotCount)), - mComposerClient(client), - mDisplay(display) {} + TestLayer(const std::shared_ptr& client, Display display) + : mLayer(client->createLayer(display, kBufferSlotCount)), mComposerClient(client) {} - virtual ~TestLayer() { mComposerClient->destroyLayer(mDisplay, mLayer); } + // ComposerClient will take care of destroying layers, no need to explicitly + // call destroyLayers here + virtual ~TestLayer(){}; - virtual void write(std::shared_ptr writer) { + virtual void write(const std::shared_ptr& writer) { writer->selectLayer(mLayer); writer->setLayerDisplayFrame(mDisplayFrame); + writer->setLayerSourceCrop(mSourceCrop); writer->setLayerZOrder(mZOrder); + writer->setLayerSurfaceDamage(mSurfaceDamage); + writer->setLayerTransform(mTransform); + writer->setLayerPlaneAlpha(mAlpha); + writer->setLayerBlendMode(mBlendMode); } void setDisplayFrame(IComposerClient::Rect frame) { mDisplayFrame = frame; } + void setSourceCrop(IComposerClient::FRect crop) { mSourceCrop = crop; } void setZOrder(uint32_t z) { mZOrder = z; } + void setSurfaceDamage(std::vector surfaceDamage) { + mSurfaceDamage = surfaceDamage; + } + + void setTransform(Transform transform) { mTransform = transform; } + void setAlpha(float alpha) { mAlpha = alpha; } + void setBlendMode(IComposerClient::BlendMode blendMode) { mBlendMode = blendMode; } + + static constexpr uint32_t kBufferSlotCount = 64; + + IComposerClient::Rect mDisplayFrame = {0, 0, 0, 0}; + uint32_t mZOrder = 0; + std::vector mSurfaceDamage; + Transform mTransform = static_cast(0); + IComposerClient::FRect mSourceCrop = {0, 0, 0, 0}; + float mAlpha = 1.0; + IComposerClient::BlendMode mBlendMode = IComposerClient::BlendMode::NONE; + protected: Layer mLayer; - IComposerClient::Rect mDisplayFrame = {0, 0, 0, 0}; - uint32_t mZOrder = 0; private: std::shared_ptr const mComposerClient; - const Display mDisplay; - static constexpr uint32_t kBufferSlotCount = 64; -}; - -class TestColorLayer : public TestLayer { - public: - TestColorLayer(std::shared_ptr const client, Display display) - : TestLayer{client, display} {} - - void write(std::shared_ptr writer) override { - TestLayer::write(writer); - writer->setLayerCompositionType(IComposerClient::Composition::SOLID_COLOR); - writer->setLayerColor(mColor); - } - - void setColor(IComposerClient::Color color) { mColor = color; } - - private: - IComposerClient::Color mColor = {0xff, 0xff, 0xff, 0xff}; }; class GraphicsComposerReadbackTest : public ::testing::VtsHalHidlTargetTestBase { - protected: - using PowerMode = V2_1::IComposerClient::PowerMode; - void SetUp() override { - ASSERT_NO_FATAL_FAILURE( - mComposer = std::make_unique( - GraphicsComposerHidlEnvironment::Instance()->getServiceName())); - ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient()); - mComposerCallback = new V2_1::vts::GraphicsComposerCallback; - mComposerClient->registerCallback(mComposerCallback); - - // assume the first display is primary and is never removed - mPrimaryDisplay = waitForFirstDisplay(); - Config activeConfig = mComposerClient->getActiveConfig(mPrimaryDisplay); - mDisplayWidth = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig, - IComposerClient::Attribute::WIDTH); - mDisplayHeight = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig, - IComposerClient::Attribute::HEIGHT); - - // explicitly disable vsync - mComposerClient->setVsyncEnabled(mPrimaryDisplay, false); - mComposerCallback->setVsyncAllowed(false); - - // set up command writer/reader and gralloc - mWriter = std::make_shared(1024); - mReader = std::make_unique(); - mGralloc = std::make_unique(); - - mComposerClient->getRaw()->getReadbackBufferAttributes( - mPrimaryDisplay, [&](const auto& tmpError, const auto&, const auto&) { - mHasReadbackBuffer = tmpError == Error::NONE; - }); - } - - ~GraphicsComposerReadbackTest() override { - if (mComposerCallback != nullptr) { - EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount()); - EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount()); - EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount()); - } - } - - void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); } - - void render(const std::vector>& layers) { - for (auto layer : layers) { - layer->write(mWriter); - } - execute(); - mWriter->validateDisplay(); - mWriter->presentDisplay(); - execute(); - } - - int32_t GetBytesPerPixel(PixelFormat format) { - switch (format) { + public: + static int32_t GetBytesPerPixel(PixelFormat pixelFormat) { + switch (pixelFormat) { case PixelFormat::RGBA_8888: return 4; case PixelFormat::RGB_888: @@ -170,9 +127,120 @@ class GraphicsComposerReadbackTest : public ::testing::VtsHalHidlTargetTestBase } } + static void fillBuffer(int32_t width, int32_t height, uint32_t stride, void* bufferData, + PixelFormat pixelFormat, + std::vector desiredPixelColors) { + ASSERT_TRUE(pixelFormat == PixelFormat::RGB_888 || pixelFormat == PixelFormat::RGBA_8888); + int32_t bytesPerPixel = GetBytesPerPixel(pixelFormat); + ASSERT_NE(-1, bytesPerPixel); + for (int row = 0; row < height; row++) { + for (int col = 0; col < width; col++) { + int pixel = row * width + col; + IComposerClient::Color srcColor = desiredPixelColors[pixel]; + + int offset = (row * stride + col) * bytesPerPixel; + uint8_t* pixelColor = (uint8_t*)bufferData + offset; + pixelColor[0] = srcColor.r; + pixelColor[1] = srcColor.g; + pixelColor[2] = srcColor.b; + + if (bytesPerPixel == 4) { + pixelColor[3] = srcColor.a; + } + } + } + } + + protected: + using PowerMode = V2_1::IComposerClient::PowerMode; + void SetUp() override { + VtsHalHidlTargetTestBase::SetUp(); + ASSERT_NO_FATAL_FAILURE( + mComposer = std::make_unique( + GraphicsComposerHidlEnvironment::Instance()->getServiceName())); + ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient()); + mComposerCallback = new V2_1::vts::GraphicsComposerCallback; + mComposerClient->registerCallback(mComposerCallback); + + // assume the first display is primary and is never removed + mPrimaryDisplay = waitForFirstDisplay(); + Config activeConfig; + ASSERT_NO_FATAL_FAILURE(activeConfig = mComposerClient->getActiveConfig(mPrimaryDisplay)); + ASSERT_NO_FATAL_FAILURE( + mDisplayWidth = mComposerClient->getDisplayAttribute( + mPrimaryDisplay, activeConfig, IComposerClient::Attribute::WIDTH)); + ASSERT_NO_FATAL_FAILURE( + mDisplayHeight = mComposerClient->getDisplayAttribute( + mPrimaryDisplay, activeConfig, IComposerClient::Attribute::HEIGHT)); + + // explicitly disable vsync + ASSERT_NO_FATAL_FAILURE(mComposerClient->setVsyncEnabled(mPrimaryDisplay, false)); + mComposerCallback->setVsyncAllowed(false); + + // set up command writer/reader and gralloc + mWriter = std::make_shared(1024); + mReader = std::make_unique(); + mGralloc = std::make_shared(); + + mComposerClient->getRaw()->getReadbackBufferAttributes( + mPrimaryDisplay, + [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) { + mHasReadbackBuffer = readbackSupported(tmpPixelFormat, tmpDataspace, tmpError); + mPixelFormat = tmpPixelFormat; + mDataspace = tmpDataspace; + }); + ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::ON)); + } + + void TearDown() override { + mWriter->validateDisplay(); + mWriter->presentDisplay(); + execute(); + ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::OFF)); + EXPECT_EQ(0, mReader->mErrors.size()); + EXPECT_EQ(0, mReader->mCompositionChanges.size()); + if (mComposerCallback != nullptr) { + EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount()); + EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount()); + EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount()); + } + VtsHalHidlTargetTestBase::TearDown(); + } + + void execute() { + ASSERT_NO_FATAL_FAILURE(mComposerClient->execute(mReader.get(), mWriter.get())); + } + + void writeLayers(const std::vector>& layers) { + for (auto layer : layers) { + layer->write(mWriter); + } + execute(); + } + + void clearColors(std::vector& expectedColors, int32_t width, + int32_t height) { + for (int row = 0; row < height; row++) { + for (int col = 0; col < width; col++) { + int pixel = row * mDisplayWidth + col; + expectedColors[pixel] = BLACK; + } + } + } + + void fillColorsArea(std::vector& expectedColors, int32_t stride, + IComposerClient::Rect area, IComposerClient::Color color) { + for (int row = area.top; row < area.bottom; row++) { + for (int col = area.left; col < area.right; col++) { + int pixel = row * stride + col; + expectedColors[pixel] = color; + } + } + } + bool readbackSupported(const PixelFormat& pixelFormat, const Dataspace& dataspace, const Error error) { - if (error == Error::UNSUPPORTED) { + if (error != Error::NONE) { return false; } // TODO: add support for RGBA_1010102 @@ -185,33 +253,6 @@ class GraphicsComposerReadbackTest : public ::testing::VtsHalHidlTargetTestBase return true; } - void getReadbackBufferAttributes(Display display, PixelFormat* outPixelFormat, - Dataspace* outDataspace) { - mComposerClient->getRaw()->getReadbackBufferAttributes( - display, [&](const auto&, const auto& tmpOutPixelFormat, const auto& tmpOutDataspace) { - *outPixelFormat = tmpOutPixelFormat; - *outDataspace = tmpOutDataspace; - }); - } - - void checkReadbackBuffer(IMapper::BufferDescriptorInfo info, uint32_t stride, void* bufferData, - std::vector expectedColors) { - int32_t bytesPerPixel = GetBytesPerPixel(info.format); - ASSERT_NE(-1, bytesPerPixel) - << "unexpected pixel format " << static_cast(info.format) - << "(expected RGBA_8888 or RGB_888)"; - for (int row = 0; row < mDisplayHeight; row++) { - for (int col = 0; col < mDisplayWidth; col++) { - int pixel = row * mDisplayWidth + col; - int offset = (row * stride + col) * bytesPerPixel; - uint8_t* pixelColor = (uint8_t*)bufferData + offset; - - EXPECT_EQ(expectedColors[pixel].r, pixelColor[0]); - EXPECT_EQ(expectedColors[pixel].g, pixelColor[1]); - EXPECT_EQ(expectedColors[pixel].b, pixelColor[2]); - } - } - } std::unique_ptr mComposer; std::shared_ptr mComposerClient; @@ -223,9 +264,13 @@ class GraphicsComposerReadbackTest : public ::testing::VtsHalHidlTargetTestBase int32_t mDisplayHeight; std::shared_ptr mWriter; std::unique_ptr mReader; - std::unique_ptr mGralloc; + std::shared_ptr mGralloc; bool mHasReadbackBuffer; + PixelFormat mPixelFormat; + Dataspace mDataspace; + + static constexpr uint32_t kClientTargetSlotCount = 64; private: Display waitForFirstDisplay() { @@ -239,6 +284,178 @@ class GraphicsComposerReadbackTest : public ::testing::VtsHalHidlTargetTestBase } } }; +class ReadbackBuffer { + public: + ReadbackBuffer(Display display, const std::shared_ptr& client, + const std::shared_ptr& gralloc, uint32_t width, uint32_t height, + PixelFormat pixelFormat, Dataspace dataspace) { + mDisplay = display; + + mComposerClient = client; + mGralloc = gralloc; + + mPixelFormat = pixelFormat; + mDataspace = dataspace; + + mInfo.width = width; + mInfo.height = height; + mInfo.layerCount = 1; + mInfo.format = mPixelFormat; + mInfo.usage = static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::GPU_TEXTURE); + + mAccessRegion.top = 0; + mAccessRegion.left = 0; + mAccessRegion.width = width; + mAccessRegion.height = height; + }; + + ~ReadbackBuffer() { + if (mBufferHandle != nullptr) { + mGralloc->freeBuffer(mBufferHandle); + } + } + + void setReadbackBuffer() { + if (mBufferHandle != nullptr) { + mGralloc->freeBuffer(mBufferHandle); + mBufferHandle = nullptr; + } + mBufferHandle = mGralloc->allocate(mInfo, /*import*/ true, &mStride); + ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle, mInfo, mStride)); + ASSERT_NO_FATAL_FAILURE(mComposerClient->setReadbackBuffer(mDisplay, mBufferHandle, -1)); + } + + void checkReadbackBuffer(std::vector expectedColors) { + // lock buffer for reading + int32_t fenceHandle; + ASSERT_NO_FATAL_FAILURE(mComposerClient->getReadbackBufferFence(mDisplay, &fenceHandle)); + + void* bufData = mGralloc->lock(mBufferHandle, mInfo.usage, mAccessRegion, fenceHandle); + ASSERT_TRUE(mPixelFormat == PixelFormat::RGB_888 || mPixelFormat == PixelFormat::RGBA_8888); + int32_t bytesPerPixel = GraphicsComposerReadbackTest::GetBytesPerPixel(mPixelFormat); + ASSERT_NE(-1, bytesPerPixel); + for (int row = 0; row < mInfo.height; row++) { + for (int col = 0; col < mInfo.width; col++) { + int pixel = row * mInfo.width + col; + int offset = (row * mStride + col) * bytesPerPixel; + uint8_t* pixelColor = (uint8_t*)bufData + offset; + + ASSERT_EQ(expectedColors[pixel].r, pixelColor[0]); + ASSERT_EQ(expectedColors[pixel].g, pixelColor[1]); + ASSERT_EQ(expectedColors[pixel].b, pixelColor[2]); + } + } + int32_t unlockFence = mGralloc->unlock(mBufferHandle); + if (unlockFence != -1) { + sync_wait(unlockFence, -1); + close(unlockFence); + } + } + + protected: + IMapper::BufferDescriptorInfo mInfo; + IMapper::Rect mAccessRegion; + uint32_t mStride; + const native_handle_t* mBufferHandle = nullptr; + PixelFormat mPixelFormat; + Dataspace mDataspace; + Display mDisplay; + std::shared_ptr mGralloc; + std::shared_ptr mComposerClient; +}; + +class TestColorLayer : public TestLayer { + public: + TestColorLayer(const std::shared_ptr& client, Display display) + : TestLayer{client, display} {} + + void write(const std::shared_ptr& writer) override { + TestLayer::write(writer); + writer->setLayerCompositionType(IComposerClient::Composition::SOLID_COLOR); + writer->setLayerColor(mColor); + } + + void setColor(IComposerClient::Color color) { mColor = color; } + + private: + IComposerClient::Color mColor = {0xff, 0xff, 0xff, 0xff}; +}; + +class TestBufferLayer : public TestLayer { + public: + TestBufferLayer(const std::shared_ptr& client, + const std::shared_ptr& gralloc, Display display, int32_t width, + int32_t height, PixelFormat format, + IComposerClient::Composition composition = IComposerClient::Composition::DEVICE) + : TestLayer{client, display} { + mGralloc = gralloc; + mComposition = composition; + mInfo.width = width; + mInfo.height = height; + mInfo.layerCount = 1; + mInfo.format = format; + mInfo.usage = + static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY); + + mAccessRegion.top = 0; + mAccessRegion.left = 0; + mAccessRegion.width = width; + mAccessRegion.height = height; + + setSourceCrop({0, 0, (float)width, (float)height}); + } + + ~TestBufferLayer() { + if (mBufferHandle != nullptr) { + mGralloc->freeBuffer(mBufferHandle); + } + } + + void write(const std::shared_ptr& writer) override { + TestLayer::write(writer); + writer->setLayerCompositionType(mComposition); + writer->setLayerDataspace(Dataspace::UNKNOWN); + writer->setLayerVisibleRegion(std::vector(1, mDisplayFrame)); + if (mBufferHandle != nullptr) writer->setLayerBuffer(0, mBufferHandle, mFillFence); + } + + void fillBuffer(std::vector expectedColors) { + void* bufData = mGralloc->lock(mBufferHandle, mInfo.usage, mAccessRegion, -1); + ASSERT_NO_FATAL_FAILURE(GraphicsComposerReadbackTest::fillBuffer( + mInfo.width, mInfo.height, mStride, bufData, mInfo.format, expectedColors)); + mFillFence = mGralloc->unlock(mBufferHandle); + if (mFillFence != -1) { + sync_wait(mFillFence, -1); + close(mFillFence); + } + } + void setBuffer(std::vector colors) { + if (mBufferHandle != nullptr) { + mGralloc->freeBuffer(mBufferHandle); + mBufferHandle = nullptr; + } + mBufferHandle = mGralloc->allocate(mInfo, /*import*/ true, &mStride); + ASSERT_NE(nullptr, mBufferHandle); + ASSERT_NO_FATAL_FAILURE(fillBuffer(colors)); + ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle, mInfo, mStride)); + } + + void setToClientComposition(const std::shared_ptr& writer) { + writer->selectLayer(mLayer); + writer->setLayerCompositionType(IComposerClient::Composition::CLIENT); + } + + IMapper::BufferDescriptorInfo mInfo; + IMapper::Rect mAccessRegion; + uint32_t mStride; + + protected: + IComposerClient::Composition mComposition; + std::shared_ptr mGralloc; + int32_t mFillFence; + const native_handle_t* mBufferHandle = nullptr; +}; TEST_F(GraphicsComposerReadbackTest, SingleSolidColorLayer) { if (!mHasReadbackBuffer) { @@ -246,13 +463,12 @@ TEST_F(GraphicsComposerReadbackTest, SingleSolidColorLayer) { return; } mWriter->selectDisplay(mPrimaryDisplay); - mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::ON); - mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, RenderIntent::COLORIMETRIC); + ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, + RenderIntent::COLORIMETRIC)); auto layer = std::make_shared(mComposerClient, mPrimaryDisplay); - IComposerClient::Color color({0, 0, 0xff, 0xff}); - IComposerClient::Rect coloredSquare({100, 100, 500, 500}); - layer->setColor(color); + IComposerClient::Rect coloredSquare({0, 0, mDisplayWidth, mDisplayHeight}); + layer->setColor(BLUE); layer->setDisplayFrame(coloredSquare); layer->setZOrder(10); @@ -260,58 +476,831 @@ TEST_F(GraphicsComposerReadbackTest, SingleSolidColorLayer) { // expected color for each pixel std::vector expectedColors(mDisplayWidth * mDisplayHeight); - for (int row = 0; row < mDisplayHeight; row++) { - for (int col = 0; col < mDisplayWidth; col++) { - int pixel = row * mDisplayWidth + col; - if (row >= coloredSquare.top && row < coloredSquare.bottom && - col >= coloredSquare.left && col < coloredSquare.right) { - expectedColors[pixel] = color; - } else { - expectedColors[pixel] = {0, 0, 0, 0xff}; + fillColorsArea(expectedColors, mDisplayWidth, coloredSquare, BLUE); + + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + + writeLayers(layers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + // if hwc cannot handle and asks for composition change, + // just succeed the test + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +TEST_F(GraphicsComposerReadbackTest, SetLayerBuffer) { + if (!mHasReadbackBuffer) { + GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; + return; + } + + mWriter->selectDisplay(mPrimaryDisplay); + + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight / 4}, RED); + fillColorsArea(expectedColors, mDisplayWidth, + {0, mDisplayHeight / 4, mDisplayWidth, mDisplayHeight / 2}, GREEN); + fillColorsArea(expectedColors, mDisplayWidth, + {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, BLUE); + + auto layer = + std::make_shared(mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth, + mDisplayHeight, PixelFormat::RGBA_8888); + layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); + layer->setZOrder(10); + ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors)); + + std::vector> layers = {layer}; + + writeLayers(layers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + ASSERT_EQ(0, mReader->mErrors.size()); + + mWriter->presentDisplay(); + execute(); + + ASSERT_EQ(0, mReader->mErrors.size()); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +TEST_F(GraphicsComposerReadbackTest, SetLayerBufferNoEffect) { + if (!mHasReadbackBuffer) { + GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; + return; + } + + mWriter->selectDisplay(mPrimaryDisplay); + ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, + RenderIntent::COLORIMETRIC)); + + auto layer = std::make_shared(mComposerClient, mPrimaryDisplay); + IComposerClient::Rect coloredSquare({0, 0, mDisplayWidth, mDisplayHeight}); + layer->setColor(BLUE); + layer->setDisplayFrame(coloredSquare); + layer->setZOrder(10); + layer->write(mWriter); + + // This following buffer call should have no effect + IMapper::BufferDescriptorInfo bufferInfo{}; + bufferInfo.width = mDisplayWidth; + bufferInfo.height = mDisplayHeight; + bufferInfo.layerCount = 1; + bufferInfo.format = PixelFormat::RGBA_8888; + bufferInfo.usage = + static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN); + const native_handle_t* bufferHandle = mGralloc->allocate(bufferInfo); + mWriter->setLayerBuffer(0, bufferHandle, -1); + + // expected color for each pixel + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + fillColorsArea(expectedColors, mDisplayWidth, coloredSquare, BLUE); + + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + + mWriter->validateDisplay(); + execute(); + + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +TEST_F(GraphicsComposerReadbackTest, ClientComposition) { + if (!mHasReadbackBuffer) { + GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; + return; + } + + mWriter->selectDisplay(mPrimaryDisplay); + + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight / 4}, RED); + fillColorsArea(expectedColors, mDisplayWidth, + {0, mDisplayHeight / 4, mDisplayWidth, mDisplayHeight / 2}, GREEN); + fillColorsArea(expectedColors, mDisplayWidth, + {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, BLUE); + + auto layer = + std::make_shared(mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth, + mDisplayHeight, PixelFormat::RGBA_FP16); + layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); + layer->setZOrder(10); + + std::vector> layers = {layer}; + + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + writeLayers(layers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + + if (mReader->mCompositionChanges.size() != 0) { + ASSERT_EQ(1, mReader->mCompositionChanges.size()); + ASSERT_EQ(1, mReader->mCompositionChanges[0].second); + + ASSERT_NO_FATAL_FAILURE( + mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kClientTargetSlotCount)); + + // create client target buffer + uint32_t clientStride; + IMapper::BufferDescriptorInfo clientInfo; + clientInfo.width = layer->mInfo.width; + clientInfo.height = layer->mInfo.height; + clientInfo.layerCount = layer->mInfo.layerCount; + clientInfo.format = PixelFormat::RGBA_8888; + clientInfo.usage = + static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_CLIENT_TARGET); + const native_handle_t* clientBufferHandle = + mGralloc->allocate(clientInfo, /*import*/ true, &clientStride); + ASSERT_NE(nullptr, clientBufferHandle); + + void* clientBufData = + mGralloc->lock(clientBufferHandle, clientInfo.usage, layer->mAccessRegion, -1); + + ASSERT_NO_FATAL_FAILURE(fillBuffer(clientInfo.width, clientInfo.height, clientStride, + clientBufData, clientInfo.format, expectedColors)); + int clientFence = mGralloc->unlock(clientBufferHandle); + if (clientFence != -1) { + sync_wait(clientFence, -1); + close(clientFence); + } + + IComposerClient::Rect damage{0, 0, mDisplayWidth, mDisplayHeight}; + mWriter->setClientTarget(0, clientBufferHandle, clientFence, Dataspace::UNKNOWN, + std::vector(1, damage)); + + layer->setToClientComposition(mWriter); + mWriter->validateDisplay(); + execute(); + ASSERT_EQ(0, mReader->mCompositionChanges.size()); + } + ASSERT_EQ(0, mReader->mErrors.size()); + + mWriter->presentDisplay(); + execute(); + + ASSERT_EQ(0, mReader->mErrors.size()); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +TEST_F(GraphicsComposerReadbackTest, DeviceAndClientComposition) { + if (!mHasReadbackBuffer) { + GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; + return; + } + + mWriter->selectDisplay(mPrimaryDisplay); + ASSERT_NO_FATAL_FAILURE( + mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kClientTargetSlotCount)); + + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight / 2}, GREEN); + fillColorsArea(expectedColors, mDisplayWidth, + {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, RED); + + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + + auto deviceLayer = + std::make_shared(mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth, + mDisplayHeight / 2, PixelFormat::RGBA_8888); + std::vector deviceColors(deviceLayer->mInfo.width * + deviceLayer->mInfo.height); + fillColorsArea(deviceColors, deviceLayer->mInfo.width, + {0, 0, static_cast(deviceLayer->mInfo.width), + static_cast(deviceLayer->mInfo.height)}, + GREEN); + deviceLayer->setDisplayFrame({0, 0, static_cast(deviceLayer->mInfo.width), + static_cast(deviceLayer->mInfo.height)}); + deviceLayer->setZOrder(10); + ASSERT_NO_FATAL_FAILURE(deviceLayer->setBuffer(deviceColors)); + deviceLayer->write(mWriter); + + auto clientLayer = std::make_shared( + mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth, mDisplayHeight / 2, + PixelFormat::RGBA_8888, IComposerClient::Composition::CLIENT); + IComposerClient::Rect clientFrame = {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}; + clientLayer->setDisplayFrame(clientFrame); + clientLayer->setZOrder(0); + clientLayer->write(mWriter); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + + IMapper::BufferDescriptorInfo clientInfo; + clientInfo.width = mDisplayWidth; + clientInfo.height = mDisplayHeight; + clientInfo.layerCount = 1; + clientInfo.format = PixelFormat::RGBA_8888; + clientInfo.usage = + static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_CLIENT_TARGET); + + uint32_t clientStride; + const native_handle_t* clientBufferHandle = + mGralloc->allocate(clientInfo, /*import*/ true, &clientStride); + ASSERT_NE(nullptr, clientBufferHandle); + + IMapper::Rect clientAccessRegion; + clientAccessRegion.left = 0; + clientAccessRegion.top = 0; + clientAccessRegion.width = mDisplayWidth; + clientAccessRegion.height = mDisplayHeight; + void* clientData = mGralloc->lock(clientBufferHandle, clientInfo.usage, clientAccessRegion, -1); + std::vector clientColors(clientInfo.width * clientInfo.height); + fillColorsArea(clientColors, clientInfo.width, clientFrame, RED); + ASSERT_NO_FATAL_FAILURE(fillBuffer(clientInfo.width, clientInfo.height, clientStride, + clientData, clientInfo.format, clientColors)); + int clientFence = mGralloc->unlock(clientBufferHandle); + if (clientFence != -1) { + sync_wait(clientFence, -1); + close(clientFence); + } + + mWriter->setClientTarget(0, clientBufferHandle, clientFence, Dataspace::UNKNOWN, + std::vector(1, clientFrame)); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +TEST_F(GraphicsComposerReadbackTest, SetLayerDamage) { + if (!mHasReadbackBuffer) { + GTEST_SUCCEED() << "Readback not supported or unsupported pixelformat/dataspace"; + return; + } + + mWriter->selectDisplay(mPrimaryDisplay); + + IComposerClient::Rect redRect = {0, 0, mDisplayWidth / 4, mDisplayHeight / 4}; + + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + fillColorsArea(expectedColors, mDisplayWidth, redRect, RED); + + auto layer = + std::make_shared(mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth, + mDisplayHeight, PixelFormat::RGBA_8888); + layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); + layer->setZOrder(10); + ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors)); + + std::vector> layers = {layer}; + + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + + writeLayers(layers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); + + // update surface damage and recheck + redRect = {mDisplayWidth / 4, mDisplayHeight / 4, mDisplayWidth / 2, mDisplayHeight / 2}; + clearColors(expectedColors, mDisplayWidth, mDisplayHeight); + fillColorsArea(expectedColors, mDisplayWidth, redRect, RED); + + ASSERT_NO_FATAL_FAILURE(layer->fillBuffer(expectedColors)); + layer->setSurfaceDamage( + std::vector(1, {0, 0, mDisplayWidth / 2, mDisplayWidth / 2})); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + + writeLayers(layers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + ASSERT_EQ(0, mReader->mCompositionChanges.size()); + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +TEST_F(GraphicsComposerReadbackTest, SetLayerPlaneAlpha) { + if (!mHasReadbackBuffer) { + GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; + return; + } + + mWriter->selectDisplay(mPrimaryDisplay); + ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, + RenderIntent::COLORIMETRIC)); + + auto layer = std::make_shared(mComposerClient, mPrimaryDisplay); + layer->setColor(RED); + layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); + layer->setZOrder(10); + layer->setAlpha(0); + layer->setBlendMode(IComposerClient::BlendMode::PREMULTIPLIED); + + std::vector> layers = {layer}; + + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + + writeLayers(layers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + ASSERT_EQ(0, mReader->mErrors.size()); + + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +TEST_F(GraphicsComposerReadbackTest, SetLayerSourceCrop) { + if (!mHasReadbackBuffer) { + GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; + return; + } + + mWriter->selectDisplay(mPrimaryDisplay); + + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight / 4}, RED); + fillColorsArea(expectedColors, mDisplayWidth, + {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, BLUE); + + auto layer = + std::make_shared(mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth, + mDisplayHeight, PixelFormat::RGBA_8888); + layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); + layer->setZOrder(10); + layer->setSourceCrop({0, static_cast(mDisplayHeight / 2), + static_cast(mDisplayWidth), static_cast(mDisplayHeight)}); + ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors)); + + std::vector> layers = {layer}; + + // update expected colors to match crop + fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight}, BLUE); + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + writeLayers(layers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +TEST_F(GraphicsComposerReadbackTest, SetLayerZOrder) { + if (!mHasReadbackBuffer) { + GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; + return; + } + + mWriter->selectDisplay(mPrimaryDisplay); + ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, + RenderIntent::COLORIMETRIC)); + + IComposerClient::Rect redRect = {0, 0, mDisplayWidth, mDisplayHeight / 2}; + IComposerClient::Rect blueRect = {0, mDisplayHeight / 4, mDisplayWidth, mDisplayHeight}; + auto redLayer = std::make_shared(mComposerClient, mPrimaryDisplay); + redLayer->setColor(RED); + redLayer->setDisplayFrame(redRect); + + auto blueLayer = std::make_shared(mComposerClient, mPrimaryDisplay); + blueLayer->setColor(BLUE); + blueLayer->setDisplayFrame(blueRect); + blueLayer->setZOrder(5); + + std::vector> layers = {redLayer, blueLayer}; + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + + // red in front of blue + redLayer->setZOrder(10); + + // fill blue first so that red will overwrite on overlap + fillColorsArea(expectedColors, mDisplayWidth, blueRect, BLUE); + fillColorsArea(expectedColors, mDisplayWidth, redRect, RED); + + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + + writeLayers(layers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); + + redLayer->setZOrder(1); + clearColors(expectedColors, mDisplayWidth, mDisplayHeight); + fillColorsArea(expectedColors, mDisplayWidth, redRect, RED); + fillColorsArea(expectedColors, mDisplayWidth, blueRect, BLUE); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + + writeLayers(layers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + ASSERT_EQ(0, mReader->mCompositionChanges.size()); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +class GraphicsComposerBlendModeReadbackTest : public GraphicsComposerReadbackTest, + public ::testing::WithParamInterface { + public: + void SetUp() override { + GraphicsComposerReadbackTest::SetUp(); + mBackgroundColor = BLACK; + mTopLayerColor = RED; + } + + void TearDown() override { GraphicsComposerReadbackTest::TearDown(); } + + void setBackgroundColor(IComposerClient::Color color) { mBackgroundColor = color; } + + void setTopLayerColor(IComposerClient::Color color) { mTopLayerColor = color; } + + void setUpLayers(IComposerClient::BlendMode blendMode) { + mLayers.clear(); + std::vector topLayerPixelColors(mDisplayWidth * mDisplayHeight); + fillColorsArea(topLayerPixelColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight}, + mTopLayerColor); + + auto backgroundLayer = std::make_shared(mComposerClient, mPrimaryDisplay); + backgroundLayer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); + backgroundLayer->setZOrder(0); + backgroundLayer->setColor(mBackgroundColor); + + auto layer = std::make_shared(mComposerClient, mGralloc, mPrimaryDisplay, + mDisplayWidth, mDisplayHeight, + PixelFormat::RGBA_8888); + layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); + layer->setZOrder(10); + ASSERT_NO_FATAL_FAILURE(layer->setBuffer(topLayerPixelColors)); + + layer->setBlendMode(blendMode); + layer->setAlpha(GetParam()); + + mLayers.push_back(backgroundLayer); + mLayers.push_back(layer); + } + + void setExpectedColors(std::vector& expectedColors) { + ASSERT_EQ(2, mLayers.size()); + clearColors(expectedColors, mDisplayWidth, mDisplayHeight); + + auto layer = mLayers[1]; + IComposerClient::BlendMode blendMode = layer->mBlendMode; + float alpha = mTopLayerColor.a / 255.0 * layer->mAlpha; + if (blendMode == IComposerClient::BlendMode::NONE) { + for (int i = 0; i < expectedColors.size(); i++) { + expectedColors[i].r = mTopLayerColor.r * layer->mAlpha; + expectedColors[i].g = mTopLayerColor.g * layer->mAlpha; + expectedColors[i].b = mTopLayerColor.b * layer->mAlpha; + expectedColors[i].a = alpha * 255.0; + } + } else if (blendMode == IComposerClient::BlendMode::PREMULTIPLIED) { + for (int i = 0; i < expectedColors.size(); i++) { + expectedColors[i].r = + mTopLayerColor.r * layer->mAlpha + mBackgroundColor.r * (1.0 - alpha); + expectedColors[i].g = + mTopLayerColor.g * layer->mAlpha + mBackgroundColor.g * (1.0 - alpha); + expectedColors[i].b = + mTopLayerColor.b * layer->mAlpha + mBackgroundColor.b * (1.0 - alpha); + expectedColors[i].a = alpha + mBackgroundColor.a * (1.0 - alpha); + } + } else if (blendMode == IComposerClient::BlendMode::COVERAGE) { + for (int i = 0; i < expectedColors.size(); i++) { + expectedColors[i].r = mTopLayerColor.r * alpha + mBackgroundColor.r * (1.0 - alpha); + expectedColors[i].g = mTopLayerColor.g * alpha + mBackgroundColor.g * (1.0 - alpha); + expectedColors[i].b = mTopLayerColor.b * alpha + mBackgroundColor.b * (1.0 - alpha); + expectedColors[i].a = mTopLayerColor.a * alpha + mBackgroundColor.a * (1.0 - alpha); } } } - PixelFormat pixelFormat; - Dataspace dataspace; + protected: + std::vector> mLayers; + IComposerClient::Color mBackgroundColor; + IComposerClient::Color mTopLayerColor; +}; - getReadbackBufferAttributes(mPrimaryDisplay, &pixelFormat, &dataspace); - - IMapper::BufferDescriptorInfo info; - info.width = mDisplayWidth; - info.height = mDisplayHeight; - info.layerCount = 1; - info.format = pixelFormat; - info.usage = static_cast(BufferUsage::CPU_READ_OFTEN | BufferUsage::GPU_TEXTURE); - - uint32_t stride; - const native_handle_t* buffer = mGralloc->allocate(info, /*import*/ true, &stride); - mComposerClient->setReadbackBuffer(mPrimaryDisplay, buffer, -1); - - render(layers); - - int32_t fenceHandle; - mComposerClient->getReadbackBufferFence(mPrimaryDisplay, &fenceHandle); - - // lock buffer - // Create Rect accessRegion to specify reading the entire buffer - IMapper::Rect accessRegion; - accessRegion.left = 0; - accessRegion.top = 0; - accessRegion.width = info.width; - accessRegion.height = info.height; - - void* bufData = mGralloc->lock(buffer, info.usage, accessRegion, fenceHandle); - checkReadbackBuffer(info, stride, bufData, expectedColors); - int unlockFence = mGralloc->unlock(buffer); - - if (unlockFence != -1) { - close(unlockFence); +TEST_P(GraphicsComposerBlendModeReadbackTest, None) { + if (!mHasReadbackBuffer) { + GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; + return; } + mWriter->selectDisplay(mPrimaryDisplay); + + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + + setBackgroundColor(BLACK); + setTopLayerColor(TRANSLUCENT_RED); + setUpLayers(IComposerClient::BlendMode::NONE); + setExpectedColors(expectedColors); + + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + writeLayers(mLayers); + ASSERT_EQ(0, mReader->mErrors.size()); mWriter->validateDisplay(); + execute(); + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + ASSERT_EQ(0, mReader->mErrors.size()); mWriter->presentDisplay(); execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +// TODO: bug 116865056: Readback returns (245, 0, 0) for layer plane +// alpha of .2, expected 10.2 +TEST_P(GraphicsComposerBlendModeReadbackTest, DISABLED_Coverage) { + if (!mHasReadbackBuffer) { + GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; + return; + } + + mWriter->selectDisplay(mPrimaryDisplay); + + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + + setBackgroundColor(BLACK); + setTopLayerColor(TRANSLUCENT_RED); + + setUpLayers(IComposerClient::BlendMode::COVERAGE); + setExpectedColors(expectedColors); + + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + writeLayers(mLayers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +TEST_P(GraphicsComposerBlendModeReadbackTest, Premultiplied) { + if (!mHasReadbackBuffer) { + GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; + return; + } + + mWriter->selectDisplay(mPrimaryDisplay); + + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + + setBackgroundColor(BLACK); + setTopLayerColor(TRANSLUCENT_RED); + setUpLayers(IComposerClient::BlendMode::PREMULTIPLIED); + setExpectedColors(expectedColors); + + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + writeLayers(mLayers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +INSTANTIATE_TEST_CASE_P(BlendModeTest, GraphicsComposerBlendModeReadbackTest, + ::testing::Values(.2, 1.0)); + +class GraphicsComposerTransformReadbackTest : public GraphicsComposerReadbackTest { + protected: + void SetUp() override { + GraphicsComposerReadbackTest::SetUp(); + if (!mHasReadbackBuffer) { + GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; + return; + } + + mWriter->selectDisplay(mPrimaryDisplay); + ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, + RenderIntent::COLORIMETRIC)); + + auto backgroundLayer = std::make_shared(mComposerClient, mPrimaryDisplay); + backgroundLayer->setColor({0, 0, 0, 0}); + backgroundLayer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); + backgroundLayer->setZOrder(0); + + mSideLength = mDisplayWidth < mDisplayHeight ? mDisplayWidth : mDisplayHeight; + IComposerClient::Rect redRect = {0, 0, mSideLength / 2, mSideLength / 2}; + IComposerClient::Rect blueRect = {mSideLength / 2, mSideLength / 2, mSideLength, + mSideLength}; + + mLayer = + std::make_shared(mComposerClient, mGralloc, mPrimaryDisplay, + mSideLength, mSideLength, PixelFormat::RGBA_8888); + mLayer->setDisplayFrame({0, 0, mSideLength, mSideLength}); + mLayer->setZOrder(10); + + std::vector baseColors(mSideLength * mSideLength); + fillColorsArea(baseColors, mSideLength, redRect, RED); + fillColorsArea(baseColors, mSideLength, blueRect, BLUE); + ASSERT_NO_FATAL_FAILURE(mLayer->setBuffer(baseColors)); + + mLayers = {backgroundLayer, mLayer}; + } + + protected: + std::shared_ptr mLayer; + std::vector baseColors; + std::vector> mLayers; + int mSideLength; +}; + +TEST_F(GraphicsComposerTransformReadbackTest, FLIP_H) { + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + mLayer->setTransform(Transform::FLIP_H); + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + fillColorsArea(expectedColors, mDisplayWidth, + {mSideLength / 2, 0, mSideLength, mSideLength / 2}, RED); + fillColorsArea(expectedColors, mDisplayWidth, + {0, mSideLength / 2, mSideLength / 2, mSideLength}, BLUE); + + writeLayers(mLayers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +TEST_F(GraphicsComposerTransformReadbackTest, FLIP_V) { + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + + mLayer->setTransform(Transform::FLIP_V); + + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + fillColorsArea(expectedColors, mDisplayWidth, + {0, mSideLength / 2, mSideLength / 2, mSideLength}, RED); + fillColorsArea(expectedColors, mDisplayWidth, + {mSideLength / 2, 0, mSideLength, mSideLength / 2}, BLUE); + + writeLayers(mLayers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); +} + +TEST_F(GraphicsComposerTransformReadbackTest, ROT_180) { + ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, + mDisplayHeight, mPixelFormat, mDataspace); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); + + mLayer->setTransform(Transform::ROT_180); + + std::vector expectedColors(mDisplayWidth * mDisplayHeight); + fillColorsArea(expectedColors, mDisplayWidth, + {mSideLength / 2, mSideLength / 2, mSideLength, mSideLength}, RED); + fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mSideLength / 2, mSideLength / 2}, BLUE); + + writeLayers(mLayers); + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->validateDisplay(); + execute(); + if (mReader->mCompositionChanges.size() != 0) { + GTEST_SUCCEED(); + return; + } + ASSERT_EQ(0, mReader->mErrors.size()); + mWriter->presentDisplay(); + execute(); + ASSERT_EQ(0, mReader->mErrors.size()); + ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors)); } } // anonymous namespace