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

Commit 32e2e20f authored by Alec Mouri's avatar Alec Mouri
Browse files

Remove PQ/HLG tonemap tests in RenderEngine

OEMs did not reliably implement the CPU tonemapper, and these tests aren't tied to certification, so they fail on real devices. We're moving away from libtonemap in general in favor or sharing LUTs, so these tests wouldn't be useful moving forward anyway.

Bug: 357103962
Flag: EXEMPT test only
Test: courage
Change-Id: I4db9f11b42dae37d733bfb189ef2309bc41399f0
parent 593a6ed1
Loading
Loading
Loading
Loading
+0 −199
Original line number Diff line number Diff line
@@ -63,46 +63,6 @@ namespace renderengine {

namespace {

double EOTF_PQ(double channel) {
    float m1 = (2610.0 / 4096.0) / 4.0;
    float m2 = (2523.0 / 4096.0) * 128.0;
    float c1 = (3424.0 / 4096.0);
    float c2 = (2413.0 / 4096.0) * 32.0;
    float c3 = (2392.0 / 4096.0) * 32.0;

    float tmp = std::pow(std::clamp(channel, 0.0, 1.0), 1.0 / m2);
    tmp = std::fmax(tmp - c1, 0.0) / (c2 - c3 * tmp);
    return std::pow(tmp, 1.0 / m1);
}

vec3 EOTF_PQ(vec3 color) {
    return vec3(EOTF_PQ(color.r), EOTF_PQ(color.g), EOTF_PQ(color.b));
}

double EOTF_HLG(double channel) {
    const float a = 0.17883277;
    const float b = 0.28466892;
    const float c = 0.55991073;
    return channel <= 0.5 ? channel * channel / 3.0 : (exp((channel - c) / a) + b) / 12.0;
}

vec3 EOTF_HLG(vec3 color) {
    return vec3(EOTF_HLG(color.r), EOTF_HLG(color.g), EOTF_HLG(color.b));
}

double OETF_sRGB(double channel) {
    return channel <= 0.0031308 ? channel * 12.92 : (pow(channel, 1.0 / 2.4) * 1.055) - 0.055;
}

int sign(float in) {
    return in >= 0.0 ? 1 : -1;
}

vec3 OETF_sRGB(vec3 linear) {
    return vec3(sign(linear.r) * OETF_sRGB(linear.r), sign(linear.g) * OETF_sRGB(linear.g),
                sign(linear.b) * OETF_sRGB(linear.b));
}

// clang-format off
// Converts red channels to green channels, and zeroes out an existing green channel.
static const auto kRemoveGreenAndMoveRedToGreenMat4 = mat4(0, 1, 0, 0,
@@ -623,12 +583,6 @@ public:
    void drawShadowWithoutCaster(const FloatRect& castingBounds, const ShadowSettings& shadow,
                                 const ubyte4& backgroundColor);

    // Tonemaps grey values from sourceDataspace -> Display P3 and checks that GPU and CPU
    // implementations are identical Also implicitly checks that the injected tonemap shader
    // compiles
    void tonemap(ui::Dataspace sourceDataspace, std::function<vec3(vec3)> eotf,
                 std::function<vec3(vec3, float)> scaleOotf);

    void initializeRenderEngine();

    std::unique_ptr<renderengine::RenderEngine> mRE;
@@ -1423,125 +1377,6 @@ void RenderEngineTest::drawShadowWithoutCaster(const FloatRect& castingBounds,
    invokeDraw(settings, layers);
}

void RenderEngineTest::tonemap(ui::Dataspace sourceDataspace, std::function<vec3(vec3)> eotf,
                               std::function<vec3(vec3, float)> scaleOotf) {
    constexpr int32_t kGreyLevels = 256;

    const auto rect = Rect(0, 0, kGreyLevels, 1);

    constexpr float kMaxLuminance = 750.f;
    constexpr float kCurrentLuminanceNits = 500.f;
    const renderengine::DisplaySettings display{
            .physicalDisplay = rect,
            .clip = rect,
            .maxLuminance = kMaxLuminance,
            .currentLuminanceNits = kCurrentLuminanceNits,
            .outputDataspace = ui::Dataspace::DISPLAY_P3,
    };

    auto buf = std::make_shared<
            renderengine::impl::
                    ExternalTexture>(sp<GraphicBuffer>::make(kGreyLevels, 1,
                                                             HAL_PIXEL_FORMAT_RGBA_8888, 1,
                                                             GRALLOC_USAGE_SW_READ_OFTEN |
                                                                     GRALLOC_USAGE_SW_WRITE_OFTEN |
                                                                     GRALLOC_USAGE_HW_RENDER |
                                                                     GRALLOC_USAGE_HW_TEXTURE,
                                                             "input"),
                                     *mRE,
                                     renderengine::impl::ExternalTexture::Usage::READABLE |
                                             renderengine::impl::ExternalTexture::Usage::WRITEABLE);
    ASSERT_EQ(0, buf->getBuffer()->initCheck());
    {
        uint8_t* pixels;
        buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
                               reinterpret_cast<void**>(&pixels));

        uint8_t color = 0;
        for (int32_t j = 0; j < buf->getBuffer()->getHeight(); j++) {
            uint8_t* dest = pixels + (buf->getBuffer()->getStride() * j * 4);
            for (int32_t i = 0; i < buf->getBuffer()->getWidth(); i++) {
                dest[0] = color;
                dest[1] = color;
                dest[2] = color;
                dest[3] = 255;
                color++;
                dest += 4;
            }
        }
        buf->getBuffer()->unlock();
    }

    mBuffer = std::make_shared<
            renderengine::impl::
                    ExternalTexture>(sp<GraphicBuffer>::make(kGreyLevels, 1,
                                                             HAL_PIXEL_FORMAT_RGBA_8888, 1,
                                                             GRALLOC_USAGE_SW_READ_OFTEN |
                                                                     GRALLOC_USAGE_SW_WRITE_OFTEN |
                                                                     GRALLOC_USAGE_HW_RENDER |
                                                                     GRALLOC_USAGE_HW_TEXTURE,
                                                             "output"),
                                     *mRE,
                                     renderengine::impl::ExternalTexture::Usage::READABLE |
                                             renderengine::impl::ExternalTexture::Usage::WRITEABLE);
    ASSERT_EQ(0, mBuffer->getBuffer()->initCheck());

    const renderengine::LayerSettings layer{.geometry.boundaries = rect.toFloatRect(),
                                            .source =
                                                    renderengine::PixelSource{
                                                            .buffer =
                                                                    renderengine::Buffer{
                                                                            .buffer =
                                                                                    std::move(buf),
                                                                            .usePremultipliedAlpha =
                                                                                    true,
                                                                    },
                                                    },
                                            .alpha = 1.0f,
                                            .sourceDataspace = sourceDataspace};

    std::vector<renderengine::LayerSettings> layers{layer};
    invokeDraw(display, layers);

    ColorSpace displayP3 = ColorSpace::DisplayP3();
    ColorSpace bt2020 = ColorSpace::BT2020();

    tonemap::Metadata metadata{.displayMaxLuminance = 750.0f};

    auto generator = [=](Point location) {
        const double normColor = static_cast<double>(location.x) / (kGreyLevels - 1);
        const vec3 rgb = vec3(normColor, normColor, normColor);

        const vec3 linearRGB = eotf(rgb);

        const vec3 xyz = bt2020.getRGBtoXYZ() * linearRGB;

        const vec3 scaledXYZ = scaleOotf(xyz, kCurrentLuminanceNits);
        const auto gains =
                tonemap::getToneMapper()
                        ->lookupTonemapGain(static_cast<aidl::android::hardware::graphics::common::
                                                                Dataspace>(sourceDataspace),
                                            static_cast<aidl::android::hardware::graphics::common::
                                                                Dataspace>(
                                                    ui::Dataspace::DISPLAY_P3),
                                            {tonemap::
                                                     Color{.linearRGB =
                                                                   scaleOotf(linearRGB,
                                                                             kCurrentLuminanceNits),
                                                           .xyz = scaledXYZ}},
                                            metadata);
        EXPECT_EQ(1, gains.size());
        const double gain = gains.front();
        const vec3 normalizedXYZ = scaledXYZ * gain / metadata.displayMaxLuminance;

        const vec3 targetRGB = OETF_sRGB(displayP3.getXYZtoRGB() * normalizedXYZ) * 255;
        return ubyte4(static_cast<uint8_t>(targetRGB.r), static_cast<uint8_t>(targetRGB.g),
                      static_cast<uint8_t>(targetRGB.b), 255);
    };

    expectBufferColor(Rect(kGreyLevels, 1), generator, 2);
}

// TODO: b/341728634 - Clean up conditional compilation.
INSTANTIATE_TEST_SUITE_P(PerRenderEngineType, RenderEngineTest,
                         testing::Values(std::make_shared<SkiaGLESRenderEngineFactory>(),
@@ -2953,40 +2788,6 @@ TEST_P(RenderEngineTest, test_isOpaque) {
    expectBufferColor(rect, 117, 251, 76, 255);
}

TEST_P(RenderEngineTest, test_tonemapPQMatches) {
    if (!GetParam()->apiSupported()) {
        GTEST_SKIP();
    }

    initializeRenderEngine();

    tonemap(
            static_cast<ui::Dataspace>(HAL_DATASPACE_STANDARD_BT2020 |
                                       HAL_DATASPACE_TRANSFER_ST2084 | HAL_DATASPACE_RANGE_FULL),
            [](vec3 color) { return EOTF_PQ(color); },
            [](vec3 color, float) {
                static constexpr float kMaxPQLuminance = 10000.f;
                return color * kMaxPQLuminance;
            });
}

TEST_P(RenderEngineTest, test_tonemapHLGMatches) {
    if (!GetParam()->apiSupported()) {
        GTEST_SKIP();
    }

    initializeRenderEngine();

    tonemap(
            static_cast<ui::Dataspace>(HAL_DATASPACE_STANDARD_BT2020 | HAL_DATASPACE_TRANSFER_HLG |
                                       HAL_DATASPACE_RANGE_FULL),
            [](vec3 color) { return EOTF_HLG(color); },
            [](vec3 color, float currentLuminaceNits) {
                static constexpr float kMaxHLGLuminance = 1000.f;
                return color * kMaxHLGLuminance;
            });
}

TEST_P(RenderEngineTest, r8_behaves_as_mask) {
    if (!GetParam()->apiSupported()) {
        GTEST_SKIP();