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

Commit 87cf5dd4 authored by Alec Mouri's avatar Alec Mouri Committed by Automerger Merge Worker
Browse files

Merge "Align HLG and PQ color management to 203 nits == SDR max by default"...

Merge "Align HLG and PQ color management to 203 nits == SDR max by default" into udc-dev am: 39f3f87a am: e41328cf

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/native/+/22830903



Change-Id: Ia5ab87bd54b2e939e1cde7a56772b07fbfce0128
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents e0dbed5a e41328cf
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ namespace renderengine {
namespace skia {

// please keep in sync with hwui/utils/Color.cpp
// TODO: Scale by the dimming ratio here instead of in a generic 3x3 transform
// Otherwise there may be luminance shift for e.g., HLG.
sk_sp<SkColorSpace> toSkColorSpace(ui::Dataspace dataspace) {
    skcms_Matrix3x3 gamut;
    switch (dataspace & HAL_DATASPACE_STANDARD_MASK) {
@@ -61,13 +63,14 @@ sk_sp<SkColorSpace> toSkColorSpace(ui::Dataspace dataspace) {
        case HAL_DATASPACE_TRANSFER_GAMMA2_8:
            return SkColorSpace::MakeRGB({2.8f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, gamut);
        case HAL_DATASPACE_TRANSFER_ST2084:
            return SkColorSpace::MakeRGB(SkNamedTransferFn::kPQ, gamut);
            return SkColorSpace::MakeRGB({-2.f, -1.55522297832f, 1.86045365631f, 32 / 2523.0f,
                                          2413 / 128.0f, -2392 / 128.0f, 8192 / 1305.0f},
                                         gamut);
        case HAL_DATASPACE_TRANSFER_SMPTE_170M:
            return SkColorSpace::MakeRGB(SkNamedTransferFn::kRec2020, gamut);
        case HAL_DATASPACE_TRANSFER_HLG:
            // return HLG transfer but scale by 1/12
            skcms_TransferFunction hlgFn;
            if (skcms_TransferFunction_makeScaledHLGish(&hlgFn, 1.f / 12.f, 2.f, 2.f,
            if (skcms_TransferFunction_makeScaledHLGish(&hlgFn, 0.314509843, 2.f, 2.f,
                                                        1.f / 0.17883277f, 0.28466892f,
                                                        0.55991073f)) {
                return SkColorSpace::MakeRGB(hlgFn, gamut);
+4 −6
Original line number Diff line number Diff line
@@ -913,12 +913,10 @@ void SkiaRenderEngine::drawLayersInternal(
            continue;
        }

        // If we need to map to linear space or color management is disabled, then mark the source
        // image with the same colorspace as the destination surface so that Skia's color
        // management is a no-op.
        const ui::Dataspace layerDataspace = (!mUseColorManagement || requiresLinearEffect)
                ? display.outputDataspace
                : layer.sourceDataspace;
        // If color management is disabled, then mark the source image with the same colorspace as
        // the destination surface so that Skia's color management is a no-op.
        const ui::Dataspace layerDataspace =
                !mUseColorManagement ? display.outputDataspace : layer.sourceDataspace;

        SkPaint paint;
        if (layer.source.buffer.buffer) {
+10 −17
Original line number Diff line number Diff line
@@ -51,23 +51,20 @@ struct LinearEffect {
    // Input dataspace of the source colors.
    const ui::Dataspace inputDataspace = ui::Dataspace::SRGB;

    // Working dataspace for the output surface, for conversion from linear space.
    // Working dataspace for the output surface.
    const ui::Dataspace outputDataspace = ui::Dataspace::SRGB;

    // Sets whether alpha premultiplication must be undone.
    // This is required if the source colors use premultiplied alpha and is not opaque.
    const bool undoPremultipliedAlpha = false;

    // "Fake" dataspace of the source colors. This is used for applying an EOTF to compute linear
    // RGB. This is used when Skia is expected to color manage the input image based on the
    // dataspace of the provided source image and destination surface. SkRuntimeEffects use the
    // destination color space as the working color space. RenderEngine deliberately sets the color
    // space for input images and destination surfaces to be the same whenever LinearEffects are
    // expected to be used so that color-management is controlled by RenderEngine, but other users
    // of a LinearEffect may not be able to control the color space of the images and surfaces. So
    // fakeInputDataspace is used to essentially masquerade the input dataspace to be the output
    // dataspace for correct conversion to linear colors.
    ui::Dataspace fakeInputDataspace = ui::Dataspace::UNKNOWN;
    // "Fake" dataspace of the destination colors. This is used for applying an OETF to compute
    // non-linear RGB. This is used when Skia is expected to color manage the input image based on
    // the dataspace of the provided source image and destination surface. Some use-cases in
    // RenderEngine expect to apply a different OETF than what is expected by Skia. As in,
    // RenderEngine will color manage to a custom destination and "cast" the result to Skia's
    // working space.
    ui::Dataspace fakeOutputDataspace = ui::Dataspace::UNKNOWN;

    enum SkSLType { Shader, ColorFilter };
    SkSLType type = Shader;
@@ -76,7 +73,7 @@ struct LinearEffect {
static inline bool operator==(const LinearEffect& lhs, const LinearEffect& rhs) {
    return lhs.inputDataspace == rhs.inputDataspace && lhs.outputDataspace == rhs.outputDataspace &&
            lhs.undoPremultipliedAlpha == rhs.undoPremultipliedAlpha &&
            lhs.fakeInputDataspace == rhs.fakeInputDataspace;
            lhs.fakeOutputDataspace == rhs.fakeOutputDataspace;
}

struct LinearEffectHasher {
@@ -89,7 +86,7 @@ struct LinearEffectHasher {
        size_t result = std::hash<ui::Dataspace>{}(le.inputDataspace);
        result = HashCombine(result, std::hash<ui::Dataspace>{}(le.outputDataspace));
        result = HashCombine(result, std::hash<bool>{}(le.undoPremultipliedAlpha));
        return HashCombine(result, std::hash<ui::Dataspace>{}(le.fakeInputDataspace));
        return HashCombine(result, std::hash<ui::Dataspace>{}(le.fakeOutputDataspace));
    }
};

@@ -99,10 +96,6 @@ struct LinearEffectHasher {
// 2. Apply color transform matrices in linear space
std::string buildLinearEffectSkSL(const LinearEffect& linearEffect);

// Generates a shader string that applies color transforms in linear space.
// This is intended to be plugged into an SkColorFilter
std::string buildLinearEffectSkSLForColorFilter(const LinearEffect& linearEffect);

// Generates a list of uniforms to set on the LinearEffect shader above.
std::vector<tonemap::ShaderUniform> buildLinearEffectUniforms(
        const LinearEffect& linearEffect, const mat4& colorTransform, float maxDisplayLuminance,
+127 −354

File changed.

Preview size limit exceeded, changes collapsed.

+20 −22
Original line number Diff line number Diff line
@@ -35,6 +35,10 @@ MATCHER_P2(UniformEq, name, value, "") {
    return arg.name == name && arg.value == value;
}

MATCHER_P(UniformNameEq, name, "") {
    return arg.name == name;
}

template <typename T, std::enable_if_t<std::is_trivially_copyable<T>::value, bool> = true>
std::vector<uint8_t> buildUniformValue(T value) {
    std::vector<uint8_t> result;
@@ -49,50 +53,44 @@ TEST_F(ShadersTest, buildLinearEffectUniforms_selectsNoOpGamutMatrices) {
    shaders::LinearEffect effect =
            shaders::LinearEffect{.inputDataspace = ui::Dataspace::V0_SRGB_LINEAR,
                                  .outputDataspace = ui::Dataspace::V0_SRGB_LINEAR,
                                  .fakeInputDataspace = ui::Dataspace::UNKNOWN};
                                  .fakeOutputDataspace = ui::Dataspace::UNKNOWN};

    mat4 colorTransform = mat4::scale(vec4(.9, .9, .9, 1.));
    auto uniforms =
            shaders::buildLinearEffectUniforms(effect, colorTransform, 1.f, 1.f, 1.f, nullptr,
                                               aidl::android::hardware::graphics::composer3::
                                                       RenderIntent::COLORIMETRIC);
    EXPECT_THAT(uniforms, Contains(UniformEq("in_rgbToXyz", buildUniformValue<mat4>(mat4()))));
    EXPECT_THAT(uniforms,
                Contains(UniformEq("in_xyzToRgb", buildUniformValue<mat4>(colorTransform))));
                Contains(UniformEq("in_rgbToXyz",
                                   buildUniformValue<mat3>(
                                           ColorSpace::linearExtendedSRGB().getRGBtoXYZ()))));
    EXPECT_THAT(uniforms,
                Contains(UniformEq("in_xyzToSrcRgb",
                                   buildUniformValue<mat3>(
                                           ColorSpace::linearSRGB().getXYZtoRGB()))));
    // color transforms are already tested in renderengine's tests
    EXPECT_THAT(uniforms, Contains(UniformNameEq("in_colorTransform")));
}

TEST_F(ShadersTest, buildLinearEffectUniforms_selectsGamutTransformMatrices) {
    shaders::LinearEffect effect =
            shaders::LinearEffect{.inputDataspace = ui::Dataspace::V0_SRGB,
                                  .outputDataspace = ui::Dataspace::DISPLAY_P3,
                                  .fakeInputDataspace = ui::Dataspace::UNKNOWN};
                                  .fakeOutputDataspace = ui::Dataspace::UNKNOWN};

    ColorSpace inputColorSpace = ColorSpace::sRGB();
    ColorSpace outputColorSpace = ColorSpace::DisplayP3();
    auto uniforms =
            shaders::buildLinearEffectUniforms(effect, mat4(), 1.f, 1.f, 1.f, nullptr,
                                               aidl::android::hardware::graphics::composer3::
                                                       RenderIntent::COLORIMETRIC);
    EXPECT_THAT(uniforms,
                Contains(UniformEq("in_rgbToXyz",
                                   buildUniformValue<mat4>(mat4(inputColorSpace.getRGBtoXYZ())))));
                                   buildUniformValue<mat3>(
                                           ColorSpace::linearExtendedSRGB().getRGBtoXYZ()))));
    EXPECT_THAT(uniforms,
                Contains(UniformEq("in_xyzToRgb",
                                   buildUniformValue<mat4>(mat4(outputColorSpace.getXYZtoRGB())))));
}

TEST_F(ShadersTest, buildLinearEffectUniforms_respectsFakeInputDataspace) {
    shaders::LinearEffect effect =
            shaders::LinearEffect{.inputDataspace = ui::Dataspace::V0_SRGB,
                                  .outputDataspace = ui::Dataspace::DISPLAY_P3,
                                  .fakeInputDataspace = ui::Dataspace::DISPLAY_P3};

    auto uniforms =
            shaders::buildLinearEffectUniforms(effect, mat4(), 1.f, 1.f, 1.f, nullptr,
                                               aidl::android::hardware::graphics::composer3::
                                                       RenderIntent::COLORIMETRIC);
    EXPECT_THAT(uniforms, Contains(UniformEq("in_rgbToXyz", buildUniformValue<mat4>(mat4()))));
    EXPECT_THAT(uniforms, Contains(UniformEq("in_xyzToRgb", buildUniformValue<mat4>(mat4()))));
                Contains(UniformEq("in_xyzToSrcRgb",
                                   buildUniformValue<mat3>(inputColorSpace.getXYZtoRGB()))));
    EXPECT_THAT(uniforms, Contains(UniformNameEq("in_colorTransform")));
}

} // namespace android