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

Commit fe45436c authored by Sally Qi's avatar Sally Qi
Browse files

[Lut vts] add readback test

Bug: 377944262
Test: this
Change-Id: Iec108244be303b13f76a84a1fe5ca9dbdbde2737
parent e41f67d5
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -37,6 +37,12 @@ void TestLayer::write(ComposerClientWriter& writer) {
    writer.setLayerBlendMode(mDisplay, mLayer, mBlendMode);
    writer.setLayerBrightness(mDisplay, mLayer, mBrightness);
    writer.setLayerDataspace(mDisplay, mLayer, mDataspace);
    Luts luts{
            .pfd = ::ndk::ScopedFileDescriptor(dup(mLuts.pfd.get())),
            .offsets = mLuts.offsets,
            .lutProperties = mLuts.lutProperties,
    };
    writer.setLayerLuts(mDisplay, mLayer, luts);
}

std::string ReadbackHelper::getColorModeString(ColorMode mode) {
@@ -103,6 +109,24 @@ LayerSettings TestLayer::toRenderEngineLayerSettings() {
    layerSettings.geometry.positionTransform = scale * translation;
    layerSettings.whitePointNits = mWhitePointNits;
    layerSettings.sourceDataspace = static_cast<::android::ui::Dataspace>(mDataspace);
    if (mLuts.pfd.get() >= 0 && mLuts.offsets) {
        std::vector<int32_t> dimensions;
        std::vector<int32_t> sizes;
        std::vector<int32_t> keys;
        dimensions.reserve(mLuts.lutProperties.size());
        sizes.reserve(mLuts.lutProperties.size());
        keys.reserve(mLuts.lutProperties.size());

        for (auto& l : mLuts.lutProperties) {
            dimensions.emplace_back(static_cast<int32_t>(l.dimension));
            sizes.emplace_back(static_cast<int32_t>(l.size));
            keys.emplace_back(static_cast<int32_t>(l.samplingKeys[0]));
        }

        layerSettings.luts = std::make_shared<::android::gui::DisplayLuts>(
                ::android::base::unique_fd(dup(mLuts.pfd.get())), *mLuts.offsets, dimensions, sizes,
                keys);
    }

    return layerSettings;
}
+5 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#pragma once

#include <aidl/android/hardware/graphics/composer3/IComposerClient.h>
#include <aidl/android/hardware/graphics/composer3/Luts.h>
#include <android-base/unique_fd.h>
#include <android/hardware/graphics/composer3/ComposerClientReader.h>
#include <android/hardware/graphics/composer3/ComposerClientWriter.h>
@@ -26,6 +27,8 @@
#include "GraphicsComposerCallback.h"
#include "VtsComposerClient.h"

using aidl::android::hardware::graphics::composer3::Luts;

namespace aidl::android::hardware::graphics::composer3::vts {

using ::android::renderengine::LayerSettings;
@@ -80,6 +83,7 @@ class TestLayer {
    void setTransform(Transform transform) { mTransform = transform; }
    void setAlpha(float alpha) { mAlpha = alpha; }
    void setBlendMode(BlendMode blendMode) { mBlendMode = blendMode; }
    void setLuts(Luts luts) { mLuts = std::move(luts); }

    BlendMode getBlendMode() const { return mBlendMode; }

@@ -105,6 +109,7 @@ class TestLayer {
    BlendMode mBlendMode = BlendMode::NONE;
    uint32_t mZOrder = 0;
    Dataspace mDataspace = Dataspace::UNKNOWN;
    Luts mLuts;
};

class TestColorLayer : public TestLayer {
+113 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <aidl/Vintf.h>
#include <aidl/android/hardware/graphics/common/BufferUsage.h>
#include <aidl/android/hardware/graphics/composer3/IComposer.h>
#include <cutils/ashmem.h>
#include <gtest/gtest.h>
#include <ui/DisplayId.h>
#include <ui/DisplayIdentification.h>
@@ -527,6 +528,118 @@ TEST_P(GraphicsCompositionTest, ClientComposition) {
    }
}

void generateLuts(Luts* luts, LutProperties::Dimension dimension, int32_t size,
                  LutProperties::SamplingKey key) {
    size_t bufferSize = dimension == LutProperties::Dimension::ONE_D
                                ? static_cast<size_t>(size) * sizeof(float)
                                : static_cast<size_t>(size * size * size) * sizeof(float);
    int32_t fd = ashmem_create_region("lut_shared_mem", bufferSize);
    void* ptr = mmap(nullptr, bufferSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    std::vector<float> buffers(static_cast<size_t>(size), 0.5f);
    memcpy(ptr, buffers.data(), bufferSize);
    munmap(ptr, bufferSize);
    luts->pfd = ndk::ScopedFileDescriptor(fd);
    luts->offsets = std::vector<int32_t>{0};
    luts->lutProperties = {LutProperties{dimension, size, {key}}};
}

TEST_P(GraphicsCompositionTest, Luts) {
    ASSERT_TRUE(
            mComposerClient->setClientTargetSlotCount(getPrimaryDisplayId(), kClientTargetSlotCount)
                    .isOk());
    const auto& [status, properties] = mComposerClient->getOverlaySupport();
    if (!status.isOk() && status.getExceptionCode() == EX_SERVICE_SPECIFIC &&
        status.getServiceSpecificError() == IComposerClient::EX_UNSUPPORTED) {
        GTEST_SKIP() << "getOverlaySupport is not supported";
        return;
    }

    if (!properties.lutProperties) {
        GTEST_SKIP() << "lutProperties is not supported";
        return;
    }

    for (const auto& lutProperties : *properties.lutProperties) {
        if (!lutProperties) {
            continue;
        }
        auto& l = *lutProperties;

        for (const auto& key : l.samplingKeys) {
            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;
                }

                common::Rect coloredSquare({0, 0, getDisplayWidth(), getDisplayHeight()});

                // expected color for each pixel
                std::vector<Color> expectedColors(
                        static_cast<size_t>(getDisplayWidth() * getDisplayHeight()));
                ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), coloredSquare,
                                               WHITE);

                auto layer = std::make_shared<TestBufferLayer>(
                        mComposerClient, *mTestRenderEngine, getPrimaryDisplayId(),
                        getDisplayWidth(), getDisplayHeight(), PixelFormat::RGBA_8888, *mWriter);
                layer->setDisplayFrame(coloredSquare);
                layer->setZOrder(10);
                layer->setDataspace(Dataspace::SRGB);

                Luts luts;
                generateLuts(&luts, l.dimension, l.size, key);
                layer->setLuts(std::move(luts));

                ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors));

                std::vector<std::shared_ptr<TestLayer>> layers = {layer};

                ReadbackBuffer readbackBuffer(getPrimaryDisplayId(), mComposerClient,
                                              getDisplayWidth(), getDisplayHeight(), mPixelFormat,
                                              mDataspace);
                ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());

                writeLayers(layers);
                ASSERT_TRUE(mReader.takeErrors().empty());
                mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
                                         VtsComposerClient::kNoFrameIntervalNs);
                execute();
                // if hwc cannot handle and asks for composition change,
                // just succeed the test
                if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
                    GTEST_SUCCEED();
                    return;
                }

                auto changedCompositionTypes =
                        mReader.takeChangedCompositionTypes(getPrimaryDisplayId());
                ASSERT_TRUE(changedCompositionTypes.empty());

                mWriter->presentDisplay(getPrimaryDisplayId());
                execute();
                ASSERT_TRUE(mReader.takeErrors().empty());

                ReadbackHelper::fillColorsArea(expectedColors, getDisplayWidth(), coloredSquare,
                                               {188.f / 255.f, 188.f / 255.f, 188.f / 255.f, 1.0f});

                ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
                mTestRenderEngine->setRenderLayers(layers);
                ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->drawLayers());
                ASSERT_NO_FATAL_FAILURE(mTestRenderEngine->checkColorBuffer(expectedColors));
            }
        }
    }
}

TEST_P(GraphicsCompositionTest, MixedColorSpaces) {
    ASSERT_TRUE(
            mComposerClient->setClientTargetSlotCount(getPrimaryDisplayId(), kClientTargetSlotCount)