Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b9556b3a authored by Alec Mouri's avatar Alec Mouri Committed by Android (Google) Code Review
Browse files

Merge "Start VTS for color management." into main

parents 6a5d7dca f6c039a4
Loading
Loading
Loading
Loading
+28 −4
Original line number Diff line number Diff line
@@ -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);
}
+11 −2
Original line number Diff line number Diff line
@@ -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;
+28 −0
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -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; }

+120 −13
Original line number Diff line number Diff line
@@ -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