Start VTS for color management.

Right now this only makes sure that extended sRGB buffers aren't
corrupted by the time it hits the display. This is especially important
for Ultra HDR, because display compensation is defined by the spec.

Bug: 276331687
Bug: 259144781
Test: VtsHalGraphicsComposer3_ReadbackTest
Change-Id: Ib6c39858289d5559ae76280ca1a0ef756f2daef0
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