Adding more Readback tests and refactoring
Bug: 111563608
Test: ./VtsHalGraphicsComposerV2_2TargetTest
--gtest_filter=GraphicsComposerReadbackTest.*
Change-Id: I0e4a8212bf08c2890747f99d5754f92821c2e2f4
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
index 91318bc..db4c914 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::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 TestLayer {
public:
- TestLayer(std::shared_ptr<ComposerClient> const client, Display display)
- : mLayer(client->createLayer(display, kBufferSlotCount)),
- mComposerClient(client),
- mDisplay(display) {}
+ TestLayer(const std::shared_ptr<ComposerClient>& 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<CommandWriterBase> writer) {
+ virtual void write(const std::shared_ptr<CommandWriterBase>& 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<IComposerClient::Rect> 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<IComposerClient::Rect> mSurfaceDamage;
+ Transform mTransform = static_cast<Transform>(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<ComposerClient> const mComposerClient;
- const Display mDisplay;
- static constexpr uint32_t kBufferSlotCount = 64;
-};
-
-class TestColorLayer : public TestLayer {
- public:
- TestColorLayer(std::shared_ptr<ComposerClient> const client, Display display)
- : TestLayer{client, display} {}
-
- void write(std::shared_ptr<CommandWriterBase> 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<Composer>(
- GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
- 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<CommandWriterBase>(1024);
- mReader = std::make_unique<TestCommandReader>();
- mGralloc = std::make_unique<Gralloc>();
-
- 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<std::shared_ptr<TestLayer>>& 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 @@
}
}
+ static void fillBuffer(int32_t width, int32_t height, uint32_t stride, void* bufferData,
+ PixelFormat pixelFormat,
+ std::vector<IComposerClient::Color> 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<Composer>(
+ GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
+ 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<CommandWriterBase>(1024);
+ mReader = std::make_unique<TestCommandReader>();
+ mGralloc = std::make_shared<Gralloc>();
+
+ 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<std::shared_ptr<TestLayer>>& layers) {
+ for (auto layer : layers) {
+ layer->write(mWriter);
+ }
+ execute();
+ }
+
+ void clearColors(std::vector<IComposerClient::Color>& 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<IComposerClient::Color>& 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 @@
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<IComposerClient::Color> expectedColors) {
- int32_t bytesPerPixel = GetBytesPerPixel(info.format);
- ASSERT_NE(-1, bytesPerPixel)
- << "unexpected pixel format " << static_cast<int32_t>(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<Composer> mComposer;
std::shared_ptr<ComposerClient> mComposerClient;
@@ -223,9 +264,13 @@
int32_t mDisplayHeight;
std::shared_ptr<CommandWriterBase> mWriter;
std::unique_ptr<TestCommandReader> mReader;
- std::unique_ptr<Gralloc> mGralloc;
+ std::shared_ptr<Gralloc> mGralloc;
bool mHasReadbackBuffer;
+ PixelFormat mPixelFormat;
+ Dataspace mDataspace;
+
+ static constexpr uint32_t kClientTargetSlotCount = 64;
private:
Display waitForFirstDisplay() {
@@ -239,6 +284,178 @@
}
}
};
+class ReadbackBuffer {
+ public:
+ ReadbackBuffer(Display display, const std::shared_ptr<ComposerClient>& client,
+ const std::shared_ptr<Gralloc>& 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<uint64_t>(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<IComposerClient::Color> 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<Gralloc> mGralloc;
+ std::shared_ptr<ComposerClient> mComposerClient;
+};
+
+class TestColorLayer : public TestLayer {
+ public:
+ TestColorLayer(const std::shared_ptr<ComposerClient>& client, Display display)
+ : TestLayer{client, display} {}
+
+ void write(const std::shared_ptr<CommandWriterBase>& 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<ComposerClient>& client,
+ const std::shared_ptr<Gralloc>& 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<uint64_t>(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<CommandWriterBase>& writer) override {
+ TestLayer::write(writer);
+ writer->setLayerCompositionType(mComposition);
+ writer->setLayerDataspace(Dataspace::UNKNOWN);
+ writer->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, mDisplayFrame));
+ if (mBufferHandle != nullptr) writer->setLayerBuffer(0, mBufferHandle, mFillFence);
+ }
+
+ void fillBuffer(std::vector<IComposerClient::Color> 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<IComposerClient::Color> 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<CommandWriterBase>& 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<Gralloc> mGralloc;
+ int32_t mFillFence;
+ const native_handle_t* mBufferHandle = nullptr;
+};
TEST_F(GraphicsComposerReadbackTest, SingleSolidColorLayer) {
if (!mHasReadbackBuffer) {
@@ -246,13 +463,12 @@
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<TestColorLayer>(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 @@
// expected color for each pixel
std::vector<IComposerClient::Color> 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<IComposerClient::Color> 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<TestBufferLayer>(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<std::shared_ptr<TestLayer>> 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<TestColorLayer>(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<uint64_t>(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<IComposerClient::Color> 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<IComposerClient::Color> 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<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth,
+ mDisplayHeight, PixelFormat::RGBA_FP16);
+ layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
+ layer->setZOrder(10);
+
+ std::vector<std::shared_ptr<TestLayer>> 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<uint64_t>(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<IComposerClient::Rect>(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<IComposerClient::Color> 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<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth,
+ mDisplayHeight / 2, PixelFormat::RGBA_8888);
+ std::vector<IComposerClient::Color> deviceColors(deviceLayer->mInfo.width *
+ deviceLayer->mInfo.height);
+ fillColorsArea(deviceColors, deviceLayer->mInfo.width,
+ {0, 0, static_cast<int32_t>(deviceLayer->mInfo.width),
+ static_cast<int32_t>(deviceLayer->mInfo.height)},
+ GREEN);
+ deviceLayer->setDisplayFrame({0, 0, static_cast<int32_t>(deviceLayer->mInfo.width),
+ static_cast<int32_t>(deviceLayer->mInfo.height)});
+ deviceLayer->setZOrder(10);
+ ASSERT_NO_FATAL_FAILURE(deviceLayer->setBuffer(deviceColors));
+ deviceLayer->write(mWriter);
+
+ auto clientLayer = std::make_shared<TestBufferLayer>(
+ 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<uint64_t>(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<IComposerClient::Color> 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<IComposerClient::Rect>(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<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+ fillColorsArea(expectedColors, mDisplayWidth, redRect, RED);
+
+ auto layer =
+ std::make_shared<TestBufferLayer>(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<std::shared_ptr<TestLayer>> 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<IComposerClient::Rect>(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<TestColorLayer>(mComposerClient, mPrimaryDisplay);
+ layer->setColor(RED);
+ layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
+ layer->setZOrder(10);
+ layer->setAlpha(0);
+ layer->setBlendMode(IComposerClient::BlendMode::PREMULTIPLIED);
+
+ std::vector<std::shared_ptr<TestLayer>> 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<IComposerClient::Color> 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<IComposerClient::Color> 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<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth,
+ mDisplayHeight, PixelFormat::RGBA_8888);
+ layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
+ layer->setZOrder(10);
+ layer->setSourceCrop({0, static_cast<float>(mDisplayHeight / 2),
+ static_cast<float>(mDisplayWidth), static_cast<float>(mDisplayHeight)});
+ ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors));
+
+ std::vector<std::shared_ptr<TestLayer>> 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<TestColorLayer>(mComposerClient, mPrimaryDisplay);
+ redLayer->setColor(RED);
+ redLayer->setDisplayFrame(redRect);
+
+ auto blueLayer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
+ blueLayer->setColor(BLUE);
+ blueLayer->setDisplayFrame(blueRect);
+ blueLayer->setZOrder(5);
+
+ std::vector<std::shared_ptr<TestLayer>> layers = {redLayer, blueLayer};
+ std::vector<IComposerClient::Color> 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<float> {
+ 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<IComposerClient::Color> topLayerPixelColors(mDisplayWidth * mDisplayHeight);
+ fillColorsArea(topLayerPixelColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight},
+ mTopLayerColor);
+
+ auto backgroundLayer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
+ backgroundLayer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
+ backgroundLayer->setZOrder(0);
+ backgroundLayer->setColor(mBackgroundColor);
+
+ auto layer = std::make_shared<TestBufferLayer>(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<IComposerClient::Color>& 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<std::shared_ptr<TestLayer>> 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<uint64_t>(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<IComposerClient::Color> 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<IComposerClient::Color> 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<IComposerClient::Color> 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<TestColorLayer>(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<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay,
+ mSideLength, mSideLength, PixelFormat::RGBA_8888);
+ mLayer->setDisplayFrame({0, 0, mSideLength, mSideLength});
+ mLayer->setZOrder(10);
+
+ std::vector<IComposerClient::Color> 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<TestBufferLayer> mLayer;
+ std::vector<IComposerClient::Color> baseColors;
+ std::vector<std::shared_ptr<TestLayer>> 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<IComposerClient::Color> 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<IComposerClient::Color> 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<IComposerClient::Color> 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