Merge "Start VTS for color management." into main
diff --git a/graphics/composer/aidl/vts/ReadbackVts.cpp b/graphics/composer/aidl/vts/ReadbackVts.cpp
index abb58e2..8605628 100644
--- a/graphics/composer/aidl/vts/ReadbackVts.cpp
+++ b/graphics/composer/aidl/vts/ReadbackVts.cpp
@@ -35,6 +35,7 @@
writer.setLayerPlaneAlpha(mDisplay, mLayer, mAlpha);
writer.setLayerBlendMode(mDisplay, mLayer, mBlendMode);
writer.setLayerBrightness(mDisplay, mLayer, mBrightness);
+ writer.setLayerDataspace(mDisplay, mLayer, mDataspace);
}
std::string ReadbackHelper::getColorModeString(ColorMode mode) {
@@ -99,6 +100,7 @@
layerSettings.geometry.positionTransform = scale * translation;
layerSettings.whitePointNits = mWhitePointNits;
+ layerSettings.sourceDataspace = static_cast<::android::ui::Dataspace>(mDataspace);
return layerSettings;
}
@@ -189,6 +191,23 @@
}
}
+void ReadbackHelper::compareColorBuffers(void* expectedBuffer, void* actualBuffer,
+ const uint32_t stride, const uint32_t width,
+ const uint32_t height, common::PixelFormat pixelFormat) {
+ const int32_t bytesPerPixel = ReadbackHelper::GetBytesPerPixel(pixelFormat);
+ ASSERT_NE(-1, bytesPerPixel);
+ for (int row = 0; row < height; row++) {
+ for (int col = 0; col < width; col++) {
+ int offset = (row * static_cast<int32_t>(stride) + col) * bytesPerPixel;
+ uint8_t* expectedColor = (uint8_t*)expectedBuffer + offset;
+ uint8_t* actualColor = (uint8_t*)actualBuffer + offset;
+ ASSERT_EQ(expectedColor[0], actualColor[0]);
+ ASSERT_EQ(expectedColor[1], actualColor[1]);
+ ASSERT_EQ(expectedColor[2], actualColor[2]);
+ }
+ }
+}
+
ReadbackBuffer::ReadbackBuffer(int64_t display, const std::shared_ptr<VtsComposerClient>& client,
int32_t width, int32_t height, common::PixelFormat pixelFormat,
common::Dataspace dataspace)
@@ -248,6 +267,15 @@
EXPECT_EQ(::android::OK, status);
}
+::android::sp<::android::GraphicBuffer> ReadbackBuffer::getBuffer() {
+ const auto& [fenceStatus, bufferFence] = mComposerClient->getReadbackBufferFence(mDisplay);
+ EXPECT_TRUE(fenceStatus.isOk());
+ if (bufferFence.get() != -1) {
+ sync_wait(bufferFence.get(), -1);
+ }
+ return mGraphicBuffer;
+}
+
void TestColorLayer::write(ComposerClientWriter& writer) {
TestLayer::write(writer);
writer.setLayerCompositionType(mDisplay, mLayer, Composition::SOLID_COLOR);
@@ -344,10 +372,6 @@
"TestBufferLayer");
}
-void TestBufferLayer::setDataspace(common::Dataspace dataspace, ComposerClientWriter& writer) {
- writer.setLayerDataspace(mDisplay, mLayer, dataspace);
-}
-
void TestBufferLayer::setToClientComposition(ComposerClientWriter& writer) {
writer.setLayerCompositionType(mDisplay, mLayer, Composition::CLIENT);
}
diff --git a/graphics/composer/aidl/vts/ReadbackVts.h b/graphics/composer/aidl/vts/ReadbackVts.h
index d5602c1..ee20573 100644
--- a/graphics/composer/aidl/vts/ReadbackVts.h
+++ b/graphics/composer/aidl/vts/ReadbackVts.h
@@ -42,6 +42,9 @@
static const Color GREEN = {0.0f, 1.0f, 0.0f, 1.0f};
static const Color BLUE = {0.0f, 0.0f, 1.0f, 1.0f};
static const Color WHITE = {1.0f, 1.0f, 1.0f, 1.0f};
+static const Color LIGHT_RED = {0.5f, 0.0f, 0.0f, 1.0f};
+static const Color LIGHT_GREEN = {0.0f, 0.5f, 0.0f, 1.0f};
+static const Color LIGHT_BLUE = {0.0f, 0.0f, 0.5f, 1.0f};
class TestRenderEngine;
@@ -71,6 +74,8 @@
mSurfaceDamage = std::move(surfaceDamage);
}
+ void setDataspace(Dataspace dataspace) { mDataspace = dataspace; }
+
void setTransform(Transform transform) { mTransform = transform; }
void setAlpha(float alpha) { mAlpha = alpha; }
void setBlendMode(BlendMode blendMode) { mBlendMode = blendMode; }
@@ -98,6 +103,7 @@
float mAlpha = 1.0;
BlendMode mBlendMode = BlendMode::NONE;
uint32_t mZOrder = 0;
+ Dataspace mDataspace = Dataspace::UNKNOWN;
};
class TestColorLayer : public TestLayer {
@@ -130,8 +136,6 @@
void setBuffer(std::vector<Color> colors);
- void setDataspace(Dataspace dataspace, ComposerClientWriter& writer);
-
void setToClientComposition(ComposerClientWriter& writer);
uint32_t getWidth() const { return mWidth; }
@@ -185,6 +189,9 @@
static void compareColorBuffers(const std::vector<Color>& expectedColors, void* bufferData,
const uint32_t stride, const uint32_t width,
const uint32_t height, PixelFormat pixelFormat);
+ static void compareColorBuffers(void* expectedBuffer, void* actualBuffer, const uint32_t stride,
+ const uint32_t width, const uint32_t height,
+ PixelFormat pixelFormat);
};
class ReadbackBuffer {
@@ -196,6 +203,8 @@
void checkReadbackBuffer(const std::vector<Color>& expectedColors);
+ ::android::sp<::android::GraphicBuffer> getBuffer();
+
protected:
uint32_t mWidth;
uint32_t mHeight;
diff --git a/graphics/composer/aidl/vts/RenderEngineVts.cpp b/graphics/composer/aidl/vts/RenderEngineVts.cpp
index d1f89d0..4e7f773 100644
--- a/graphics/composer/aidl/vts/RenderEngineVts.cpp
+++ b/graphics/composer/aidl/vts/RenderEngineVts.cpp
@@ -89,4 +89,32 @@
ASSERT_EQ(::android::OK, mGraphicBuffer->unlock());
}
+void TestRenderEngine::checkColorBuffer(const ::android::sp<::android::GraphicBuffer>& buffer) {
+ ASSERT_EQ(mGraphicBuffer->getWidth(), buffer->getWidth());
+ ASSERT_EQ(mGraphicBuffer->getHeight(), buffer->getHeight());
+ void* renderedBufferData;
+ int32_t bytesPerPixel = -1;
+ int32_t bytesPerStride = -1;
+ ASSERT_EQ(0, mGraphicBuffer->lock(static_cast<uint32_t>(mGraphicBuffer->getUsage()),
+ &renderedBufferData, &bytesPerPixel, &bytesPerStride));
+ const uint32_t renderedStride = (bytesPerPixel > 0 && bytesPerStride > 0)
+ ? static_cast<uint32_t>(bytesPerStride / bytesPerPixel)
+ : mGraphicBuffer->getStride();
+
+ void* bufferData;
+ ASSERT_EQ(0, buffer->lock(static_cast<uint32_t>(buffer->getUsage()), &bufferData,
+ &bytesPerPixel, &bytesPerStride));
+ const uint32_t bufferStride = (bytesPerPixel > 0 && bytesPerStride > 0)
+ ? static_cast<uint32_t>(bytesPerStride / bytesPerPixel)
+ : buffer->getStride();
+
+ ASSERT_EQ(renderedStride, bufferStride);
+
+ ReadbackHelper::compareColorBuffers(renderedBufferData, bufferData, bufferStride,
+ mGraphicBuffer->getWidth(), mGraphicBuffer->getHeight(),
+ mFormat);
+ ASSERT_EQ(::android::OK, buffer->unlock());
+ ASSERT_EQ(::android::OK, mGraphicBuffer->unlock());
+}
+
} // namespace aidl::android::hardware::graphics::composer3::vts
diff --git a/graphics/composer/aidl/vts/RenderEngineVts.h b/graphics/composer/aidl/vts/RenderEngineVts.h
index 612f0ea..bbe508f 100644
--- a/graphics/composer/aidl/vts/RenderEngineVts.h
+++ b/graphics/composer/aidl/vts/RenderEngineVts.h
@@ -45,6 +45,7 @@
};
void drawLayers();
void checkColorBuffer(const std::vector<Color>& expectedColors);
+ void checkColorBuffer(const ::android::sp<::android::GraphicBuffer>& buffer);
::android::renderengine::RenderEngine& getInternalRenderEngine() { return *mRenderEngine; }
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
index 4b0f336..466954f 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
@@ -70,9 +70,9 @@
ContextPriority::HIGH)
.build())));
- ::android::renderengine::DisplaySettings clientCompositionDisplay;
- clientCompositionDisplay.physicalDisplay = Rect(getDisplayWidth(), getDisplayHeight());
- clientCompositionDisplay.clip = clientCompositionDisplay.physicalDisplay;
+ mClientCompositionDisplaySettings.physicalDisplay =
+ Rect(getDisplayWidth(), getDisplayHeight());
+ mClientCompositionDisplaySettings.clip = mClientCompositionDisplaySettings.physicalDisplay;
mTestRenderEngine->initGraphicBuffer(
static_cast<uint32_t>(getDisplayWidth()), static_cast<uint32_t>(getDisplayHeight()),
@@ -81,7 +81,7 @@
static_cast<uint64_t>(common::BufferUsage::CPU_READ_OFTEN) |
static_cast<uint64_t>(common::BufferUsage::CPU_WRITE_OFTEN) |
static_cast<uint64_t>(common::BufferUsage::GPU_RENDER_TARGET)));
- mTestRenderEngine->setDisplaySettings(clientCompositionDisplay);
+ mTestRenderEngine->setDisplaySettings(mClientCompositionDisplaySettings);
}
void TearDown() override {
@@ -163,6 +163,7 @@
std::unique_ptr<TestRenderEngine> mTestRenderEngine;
common::PixelFormat mPixelFormat;
common::Dataspace mDataspace;
+ ::android::renderengine::DisplaySettings mClientCompositionDisplaySettings;
static constexpr uint32_t kClientTargetSlotCount = 64;
@@ -271,7 +272,7 @@
getDisplayHeight(), common::PixelFormat::RGBA_8888);
layer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()});
layer->setZOrder(10);
- layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), *mWriter);
+ layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode));
ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors));
std::vector<std::shared_ptr<TestLayer>> layers = {layer};
@@ -455,7 +456,7 @@
getDisplayHeight(), PixelFormat::RGBA_FP16);
layer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()});
layer->setZOrder(10);
- layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), *mWriter);
+ layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode));
std::vector<std::shared_ptr<TestLayer>> layers = {layer};
@@ -553,7 +554,7 @@
deviceLayer->setDisplayFrame({0, 0, static_cast<int32_t>(deviceLayer->getWidth()),
static_cast<int32_t>(deviceLayer->getHeight())});
deviceLayer->setZOrder(10);
- deviceLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), *mWriter);
+ deviceLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode));
ASSERT_NO_FATAL_FAILURE(deviceLayer->setBuffer(deviceColors));
deviceLayer->write(*mWriter);
@@ -640,7 +641,7 @@
getDisplayHeight(), PixelFormat::RGBA_8888);
layer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()});
layer->setZOrder(10);
- layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), *mWriter);
+ layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode));
ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors));
std::vector<std::shared_ptr<TestLayer>> layers = {layer};
@@ -768,7 +769,7 @@
getDisplayHeight(), PixelFormat::RGBA_8888);
layer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()});
layer->setZOrder(10);
- layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), *mWriter);
+ layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode));
layer->setSourceCrop({0, static_cast<float>(getDisplayHeight() / 2),
static_cast<float>(getDisplayWidth()),
static_cast<float>(getDisplayHeight())});
@@ -987,7 +988,7 @@
getDisplayHeight(), PixelFormat::RGBA_8888);
layer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()});
layer->setZOrder(10);
- layer->setDataspace(Dataspace::UNKNOWN, *mWriter);
+ layer->setDataspace(Dataspace::UNKNOWN);
ASSERT_NO_FATAL_FAILURE(layer->setBuffer(topLayerPixelColors));
layer->setBlendMode(blendMode);
@@ -1222,7 +1223,7 @@
getDisplayHeight(), mPixelFormat, mDataspace);
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
mLayer->setTransform(Transform::FLIP_H);
- mLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), *mWriter);
+ mLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode));
std::vector<Color> expectedColors(
static_cast<size_t>(getDisplayWidth() * getDisplayHeight()));
@@ -1268,7 +1269,7 @@
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
mLayer->setTransform(Transform::FLIP_V);
- mLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), *mWriter);
+ mLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode));
std::vector<Color> expectedColors(
static_cast<size_t>(getDisplayWidth() * getDisplayHeight()));
@@ -1313,7 +1314,7 @@
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
mLayer->setTransform(Transform::ROT_180);
- mLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), *mWriter);
+ mLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode));
std::vector<Color> expectedColors(
static_cast<size_t>(getDisplayWidth() * getDisplayHeight()));
@@ -1342,6 +1343,100 @@
}
}
+class GraphicsColorManagementCompositionTest
+ : public GraphicsCompositionTestBase,
+ public testing::WithParamInterface<std::tuple<std::string, Dataspace, Dataspace, Dataspace>> {
+ public:
+ void SetUp() override {
+ SetUpBase(std::get<0>(GetParam()));
+ // for some reason only sRGB reliably works
+ mTestColorModes.erase(
+ std::remove_if(mTestColorModes.begin(), mTestColorModes.end(),
+ [](ColorMode mode) { return mode != ColorMode::SRGB; }),
+ mTestColorModes.end());
+ auto standard = std::get<1>(GetParam());
+ auto transfer = std::get<2>(GetParam());
+ auto range = std::get<3>(GetParam());
+
+ mLayerDataspace = static_cast<Dataspace>(static_cast<int32_t>(standard) |
+ static_cast<int32_t>(transfer) |
+ static_cast<int32_t>(range));
+ ALOGD("Invoking test for dataspace: {%s, %s, %s}", toString(standard).c_str(),
+ toString(transfer).c_str(), toString(range).c_str());
+ }
+
+ void makeLayer() {
+ mLayer = std::make_shared<TestBufferLayer>(
+ mComposerClient, *mTestRenderEngine, getPrimaryDisplayId(), getDisplayWidth(),
+ getDisplayHeight(), common::PixelFormat::RGBA_8888);
+ mLayer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()});
+ mLayer->setZOrder(10);
+ mLayer->setAlpha(1.f);
+ mLayer->setDataspace(mLayerDataspace);
+ }
+
+ void fillColor(Color color) {
+ std::vector<Color> baseColors(static_cast<size_t>(getDisplayWidth() * getDisplayHeight()));
+ ReadbackHelper::fillColorsArea(baseColors, getDisplayWidth(),
+ common::Rect{.left = 0,
+ .top = 0,
+ .right = getDisplayWidth(),
+ .bottom = getDisplayHeight()},
+ color);
+ ASSERT_NO_FATAL_FAILURE(mLayer->setBuffer(baseColors));
+ }
+
+ Dataspace mLayerDataspace;
+ std::shared_ptr<TestBufferLayer> mLayer;
+};
+
+TEST_P(GraphicsColorManagementCompositionTest, ColorConversion) {
+ for (ColorMode mode : mTestColorModes) {
+ EXPECT_TRUE(mComposerClient
+ ->setColorMode(getPrimaryDisplayId(), mode, RenderIntent::COLORIMETRIC)
+ .isOk());
+
+ bool isSupported;
+ ASSERT_NO_FATAL_FAILURE(isSupported = getHasReadbackBuffer());
+ if (!isSupported) {
+ GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+ return;
+ }
+
+ mClientCompositionDisplaySettings.outputDataspace =
+ static_cast<::android::ui::Dataspace>(mDataspace);
+ mTestRenderEngine->setDisplaySettings(mClientCompositionDisplaySettings);
+
+ makeLayer();
+ for (auto color : {LIGHT_RED, LIGHT_GREEN, LIGHT_BLUE}) {
+ ALOGD("Testing color: %f, %f, %f, %f with color mode: %d", color.r, color.g, color.b,
+ color.a, mode);
+ ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient, getDisplayWidth(),
+ getDisplayHeight(), mPixelFormat, mDataspace);
+ ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+ fillColor(color);
+ writeLayers({mLayer});
+ EXPECT_TRUE(mComposerClient->setPowerMode(getPrimaryDisplayId(), PowerMode::ON).isOk());
+
+ ASSERT_TRUE(mReader.takeErrors().empty());
+ mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ execute();
+ if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
+ continue;
+ }
+ ASSERT_TRUE(mReader.takeErrors().empty());
+ mWriter->presentDisplay(getPrimaryDisplayId());
+ execute();
+ ASSERT_TRUE(mReader.takeErrors().empty());
+
+ mTestRenderEngine->setRenderLayers({mLayer});
+ ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers());
+ ASSERT_NO_FATAL_FAILURE(
+ mTestRenderEngine->checkColorBuffer(readbackBuffer.getBuffer()));
+ }
+ }
+}
+
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsCompositionTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, GraphicsCompositionTest,
@@ -1360,5 +1455,17 @@
testing::ValuesIn(::android::getAidlHalInstanceNames(IComposer::descriptor)),
::android::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsColorManagementCompositionTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance, GraphicsColorManagementCompositionTest,
+ testing::Combine(testing::ValuesIn(::android::getAidlHalInstanceNames(
+ IComposer::descriptor)),
+ // Only check sRGB, but verify that extended range
+ // doesn't trigger any gamma shifts
+ testing::Values(Dataspace::STANDARD_BT709),
+ testing::Values(Dataspace::TRANSFER_SRGB),
+ // Don't test limited range until we send YUV overlays
+ testing::Values(Dataspace::RANGE_FULL,
+ Dataspace::RANGE_EXTENDED)));
+
} // namespace
} // namespace aidl::android::hardware::graphics::composer3::vts