Merge "Start VTS for color management." into main

This commit is contained in:
Alec Mouri 2023-10-10 20:40:46 +00:00 committed by Android (Google) Code Review
commit b9556b3aba
5 changed files with 188 additions and 19 deletions

View file

@ -35,6 +35,7 @@ void TestLayer::write(ComposerClientWriter& writer) {
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 TestLayer::toRenderEngineLayerSettings() {
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(const std::vector<Color>& expectedColor
}
}
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 @@ void ReadbackBuffer::checkReadbackBuffer(const std::vector<Color>& expectedColor
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 @@ void TestBufferLayer::setBuffer(std::vector<Color> colors) {
"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);
}

View file

@ -42,6 +42,9 @@ static const Color TRANSLUCENT_RED = {1.0f, 0.0f, 0.0f, 0.3f};
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 @@ class TestLayer {
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 @@ class TestLayer {
float mAlpha = 1.0;
BlendMode mBlendMode = BlendMode::NONE;
uint32_t mZOrder = 0;
Dataspace mDataspace = Dataspace::UNKNOWN;
};
class TestColorLayer : public TestLayer {
@ -130,8 +136,6 @@ class TestBufferLayer : public TestLayer {
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 @@ class ReadbackHelper {
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 @@ class ReadbackBuffer {
void checkReadbackBuffer(const std::vector<Color>& expectedColors);
::android::sp<::android::GraphicBuffer> getBuffer();
protected:
uint32_t mWidth;
uint32_t mHeight;

View file

@ -89,4 +89,32 @@ void TestRenderEngine::checkColorBuffer(const std::vector<Color>& expectedColors
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

View file

@ -45,6 +45,7 @@ class TestRenderEngine {
};
void drawLayers();
void checkColorBuffer(const std::vector<Color>& expectedColors);
void checkColorBuffer(const ::android::sp<::android::GraphicBuffer>& buffer);
::android::renderengine::RenderEngine& getInternalRenderEngine() { return *mRenderEngine; }

View file

@ -70,9 +70,9 @@ class GraphicsCompositionTestBase : public ::testing::Test {
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 @@ class GraphicsCompositionTestBase : public ::testing::Test {
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 @@ class GraphicsCompositionTestBase : public ::testing::Test {
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 @@ TEST_P(GraphicsCompositionTest, SetLayerBuffer) {
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 @@ TEST_P(GraphicsCompositionTest, ClientComposition) {
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 @@ TEST_P(GraphicsCompositionTest, DeviceAndClientComposition) {
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 @@ TEST_P(GraphicsCompositionTest, SetLayerDamage) {
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 @@ TEST_P(GraphicsCompositionTest, SetLayerSourceCrop) {
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 @@ class GraphicsBlendModeCompositionTest
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 @@ TEST_P(GraphicsTransformCompositionTest, FLIP_H) {
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 @@ TEST_P(GraphicsTransformCompositionTest, FLIP_V) {
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 @@ TEST_P(GraphicsTransformCompositionTest, ROT_180) {
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 @@ TEST_P(GraphicsTransformCompositionTest, ROT_180) {
}
}
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 @@ INSTANTIATE_TEST_SUITE_P(
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