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

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

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

parents 6689c821 8a186104
Loading
Loading
Loading
Loading
+6 −3
Original line number Original line Diff line number Diff line
@@ -21,6 +21,8 @@ namespace renderengine {
namespace skia {
namespace skia {


// please keep in sync with hwui/utils/Color.cpp
// 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) {
sk_sp<SkColorSpace> toSkColorSpace(ui::Dataspace dataspace) {
    skcms_Matrix3x3 gamut;
    skcms_Matrix3x3 gamut;
    switch (dataspace & HAL_DATASPACE_STANDARD_MASK) {
    switch (dataspace & HAL_DATASPACE_STANDARD_MASK) {
@@ -61,13 +63,14 @@ sk_sp<SkColorSpace> toSkColorSpace(ui::Dataspace dataspace) {
        case HAL_DATASPACE_TRANSFER_GAMMA2_8:
        case HAL_DATASPACE_TRANSFER_GAMMA2_8:
            return SkColorSpace::MakeRGB({2.8f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, gamut);
            return SkColorSpace::MakeRGB({2.8f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, gamut);
        case HAL_DATASPACE_TRANSFER_ST2084:
        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:
        case HAL_DATASPACE_TRANSFER_SMPTE_170M:
            return SkColorSpace::MakeRGB(SkNamedTransferFn::kRec2020, gamut);
            return SkColorSpace::MakeRGB(SkNamedTransferFn::kRec2020, gamut);
        case HAL_DATASPACE_TRANSFER_HLG:
        case HAL_DATASPACE_TRANSFER_HLG:
            // return HLG transfer but scale by 1/12
            skcms_TransferFunction hlgFn;
            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,
                                                        1.f / 0.17883277f, 0.28466892f,
                                                        0.55991073f)) {
                                                        0.55991073f)) {
                return SkColorSpace::MakeRGB(hlgFn, gamut);
                return SkColorSpace::MakeRGB(hlgFn, gamut);
+4 −6
Original line number Original line Diff line number Diff line
@@ -913,12 +913,10 @@ void SkiaRenderEngine::drawLayersInternal(
            continue;
            continue;
        }
        }


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


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


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


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


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


struct LinearEffectHasher {
struct LinearEffectHasher {
@@ -89,7 +86,7 @@ struct LinearEffectHasher {
        size_t result = std::hash<ui::Dataspace>{}(le.inputDataspace);
        size_t result = std::hash<ui::Dataspace>{}(le.inputDataspace);
        result = HashCombine(result, std::hash<ui::Dataspace>{}(le.outputDataspace));
        result = HashCombine(result, std::hash<ui::Dataspace>{}(le.outputDataspace));
        result = HashCombine(result, std::hash<bool>{}(le.undoPremultipliedAlpha));
        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
// 2. Apply color transform matrices in linear space
std::string buildLinearEffectSkSL(const LinearEffect& linearEffect);
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.
// Generates a list of uniforms to set on the LinearEffect shader above.
std::vector<tonemap::ShaderUniform> buildLinearEffectUniforms(
std::vector<tonemap::ShaderUniform> buildLinearEffectUniforms(
        const LinearEffect& linearEffect, const mat4& colorTransform, float maxDisplayLuminance,
        const LinearEffect& linearEffect, const mat4& colorTransform, float maxDisplayLuminance,
+127 −354

File changed.

Preview size limit exceeded, changes collapsed.

+20 −22
Original line number Original line Diff line number Diff line
@@ -35,6 +35,10 @@ MATCHER_P2(UniformEq, name, value, "") {
    return arg.name == name && arg.value == 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>
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> buildUniformValue(T value) {
    std::vector<uint8_t> result;
    std::vector<uint8_t> result;
@@ -49,50 +53,44 @@ TEST_F(ShadersTest, buildLinearEffectUniforms_selectsNoOpGamutMatrices) {
    shaders::LinearEffect effect =
    shaders::LinearEffect effect =
            shaders::LinearEffect{.inputDataspace = ui::Dataspace::V0_SRGB_LINEAR,
            shaders::LinearEffect{.inputDataspace = ui::Dataspace::V0_SRGB_LINEAR,
                                  .outputDataspace = 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.));
    mat4 colorTransform = mat4::scale(vec4(.9, .9, .9, 1.));
    auto uniforms =
    auto uniforms =
            shaders::buildLinearEffectUniforms(effect, colorTransform, 1.f, 1.f, 1.f, nullptr,
            shaders::buildLinearEffectUniforms(effect, colorTransform, 1.f, 1.f, 1.f, nullptr,
                                               aidl::android::hardware::graphics::composer3::
                                               aidl::android::hardware::graphics::composer3::
                                                       RenderIntent::COLORIMETRIC);
                                                       RenderIntent::COLORIMETRIC);
    EXPECT_THAT(uniforms, Contains(UniformEq("in_rgbToXyz", buildUniformValue<mat4>(mat4()))));
    EXPECT_THAT(uniforms,
    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) {
TEST_F(ShadersTest, buildLinearEffectUniforms_selectsGamutTransformMatrices) {
    shaders::LinearEffect effect =
    shaders::LinearEffect effect =
            shaders::LinearEffect{.inputDataspace = ui::Dataspace::V0_SRGB,
            shaders::LinearEffect{.inputDataspace = ui::Dataspace::V0_SRGB,
                                  .outputDataspace = ui::Dataspace::DISPLAY_P3,
                                  .outputDataspace = ui::Dataspace::DISPLAY_P3,
                                  .fakeInputDataspace = ui::Dataspace::UNKNOWN};
                                  .fakeOutputDataspace = ui::Dataspace::UNKNOWN};


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

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()))));
}
}


} // namespace android
} // namespace android