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

Commit 2019fd23 authored by Sally Qi's avatar Sally Qi
Browse files

Enable more ColorSpaces in RenderEngine

Bug: 200307628
Test: librenderengine_test pass
Change-Id: I81d9e86e8a826a74d65ce378d01ab55496cdd944
parent 772b3277
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ namespace android {
namespace renderengine {
namespace skia {

// please keep in sync with hwui/utils/Color.cpp
sk_sp<SkColorSpace> toSkColorSpace(ui::Dataspace dataspace) {
    skcms_Matrix3x3 gamut;
    switch (dataspace & HAL_DATASPACE_STANDARD_MASK) {
@@ -32,6 +33,17 @@ sk_sp<SkColorSpace> toSkColorSpace(ui::Dataspace dataspace) {
        case HAL_DATASPACE_STANDARD_DCI_P3:
            gamut = SkNamedGamut::kDisplayP3;
            break;
        case HAL_DATASPACE_STANDARD_ADOBE_RGB:
            gamut = SkNamedGamut::kAdobeRGB;
            break;
        case HAL_DATASPACE_STANDARD_BT601_625:
        case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED:
        case HAL_DATASPACE_STANDARD_BT601_525:
        case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED:
        case HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE:
        case HAL_DATASPACE_STANDARD_BT470M:
        case HAL_DATASPACE_STANDARD_FILM:
        case HAL_DATASPACE_STANDARD_UNSPECIFIED:
        default:
            gamut = SkNamedGamut::kSRGB;
            break;
@@ -42,10 +54,19 @@ sk_sp<SkColorSpace> toSkColorSpace(ui::Dataspace dataspace) {
            return SkColorSpace::MakeRGB(SkNamedTransferFn::kLinear, gamut);
        case HAL_DATASPACE_TRANSFER_SRGB:
            return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, gamut);
        case HAL_DATASPACE_TRANSFER_GAMMA2_2:
            return SkColorSpace::MakeRGB({2.2f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, gamut);
        case HAL_DATASPACE_TRANSFER_GAMMA2_6:
            return SkColorSpace::MakeRGB({2.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, gamut);
        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);
        case HAL_DATASPACE_TRANSFER_SMPTE_170M:
            return SkColorSpace::MakeRGB(SkNamedTransferFn::kRec2020, gamut);
        case HAL_DATASPACE_TRANSFER_HLG:
            return SkColorSpace::MakeRGB(SkNamedTransferFn::kHLG, gamut);
        case HAL_DATASPACE_TRANSFER_UNSPECIFIED:
        default:
            return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, gamut);
    }
+194 −0
Original line number Diff line number Diff line
@@ -503,6 +503,18 @@ public:
    template <typename SourceVariant>
    void fillBufferColorTransform();

    template <typename SourceVariant>
    void fillBufferWithColorTransformAndSourceDataspace(const ui::Dataspace sourceDataspace);

    template <typename SourceVariant>
    void fillBufferColorTransformAndSourceDataspace();

    template <typename SourceVariant>
    void fillBufferWithColorTransformAndOutputDataspace(const ui::Dataspace outputDataspace);

    template <typename SourceVariant>
    void fillBufferColorTransformAndOutputDataspace();

    template <typename SourceVariant>
    void fillBufferWithColorTransformZeroLayerAlpha();

@@ -880,12 +892,104 @@ void RenderEngineTest::fillBufferWithColorTransform() {
    invokeDraw(settings, layers);
}

template <typename SourceVariant>
void RenderEngineTest::fillBufferWithColorTransformAndSourceDataspace(
        const ui::Dataspace sourceDataspace) {
    renderengine::DisplaySettings settings;
    settings.physicalDisplay = fullscreenRect();
    settings.clip = Rect(1, 1);
    settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;

    std::vector<renderengine::LayerSettings> layers;

    renderengine::LayerSettings layer;
    layer.sourceDataspace = sourceDataspace;
    layer.geometry.boundaries = Rect(1, 1).toFloatRect();
    SourceVariant::fillColor(layer, 0.5f, 0.25f, 0.125f, this);
    layer.alpha = 1.0f;

    // construct a fake color matrix
    // annihilate green and blue channels
    settings.colorTransform = mat4::scale(vec4(0.9f, 0, 0, 1));
    // set red channel to red + green
    layer.colorTransform = mat4(1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);

    layer.alpha = 1.0f;
    layer.geometry.boundaries = Rect(1, 1).toFloatRect();

    layers.push_back(layer);

    invokeDraw(settings, layers);
}

template <typename SourceVariant>
void RenderEngineTest::fillBufferColorTransform() {
    fillBufferWithColorTransform<SourceVariant>();
    expectBufferColor(fullscreenRect(), 172, 0, 0, 255, 1);
}

template <typename SourceVariant>
void RenderEngineTest::fillBufferColorTransformAndSourceDataspace() {
    unordered_map<ui::Dataspace, ubyte4> dataspaceToColorMap;
    dataspaceToColorMap[ui::Dataspace::V0_BT709] = {172, 0, 0, 255};
    dataspaceToColorMap[ui::Dataspace::BT2020] = {172, 0, 0, 255};
    dataspaceToColorMap[ui::Dataspace::ADOBE_RGB] = {172, 0, 0, 255};
    ui::Dataspace customizedDataspace = static_cast<ui::Dataspace>(
            ui::Dataspace::STANDARD_BT709 | ui::Dataspace::TRANSFER_GAMMA2_2 |
            ui::Dataspace::RANGE_FULL);
    dataspaceToColorMap[customizedDataspace] = {172, 0, 0, 255};
    for (const auto& [sourceDataspace, color] : dataspaceToColorMap) {
        fillBufferWithColorTransformAndSourceDataspace<SourceVariant>(sourceDataspace);
        expectBufferColor(fullscreenRect(), color.r, color.g, color.b, color.a, 1);
    }
}

template <typename SourceVariant>
void RenderEngineTest::fillBufferWithColorTransformAndOutputDataspace(
        const ui::Dataspace outputDataspace) {
    renderengine::DisplaySettings settings;
    settings.physicalDisplay = fullscreenRect();
    settings.clip = Rect(1, 1);
    settings.outputDataspace = outputDataspace;

    std::vector<renderengine::LayerSettings> layers;

    renderengine::LayerSettings layer;
    layer.sourceDataspace = ui::Dataspace::V0_SCRGB_LINEAR;
    layer.geometry.boundaries = Rect(1, 1).toFloatRect();
    SourceVariant::fillColor(layer, 0.5f, 0.25f, 0.125f, this);
    layer.alpha = 1.0f;

    // construct a fake color matrix
    // annihilate green and blue channels
    settings.colorTransform = mat4::scale(vec4(0.9f, 0, 0, 1));
    // set red channel to red + green
    layer.colorTransform = mat4(1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);

    layer.alpha = 1.0f;
    layer.geometry.boundaries = Rect(1, 1).toFloatRect();

    layers.push_back(layer);

    invokeDraw(settings, layers);
}

template <typename SourceVariant>
void RenderEngineTest::fillBufferColorTransformAndOutputDataspace() {
    unordered_map<ui::Dataspace, ubyte4> dataspaceToColorMap;
    dataspaceToColorMap[ui::Dataspace::V0_BT709] = {202, 0, 0, 255};
    dataspaceToColorMap[ui::Dataspace::BT2020] = {192, 0, 0, 255};
    dataspaceToColorMap[ui::Dataspace::ADOBE_RGB] = {202, 0, 0, 255};
    ui::Dataspace customizedDataspace = static_cast<ui::Dataspace>(
            ui::Dataspace::STANDARD_BT709 | ui::Dataspace::TRANSFER_GAMMA2_6 |
            ui::Dataspace::RANGE_FULL);
    dataspaceToColorMap[customizedDataspace] = {202, 0, 0, 255};
    for (const auto& [outputDataspace, color] : dataspaceToColorMap) {
        fillBufferWithColorTransformAndOutputDataspace<SourceVariant>(outputDataspace);
        expectBufferColor(fullscreenRect(), color.r, color.g, color.b, color.a, 1);
    }
}

template <typename SourceVariant>
void RenderEngineTest::fillBufferWithColorTransformZeroLayerAlpha() {
    renderengine::DisplaySettings settings;
@@ -1427,6 +1531,36 @@ TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransform_colorSource) {
    fillBufferColorTransform<ColorSourceVariant>();
}

TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransform_sourceDataspace) {
    const auto& renderEngineFactory = GetParam();
    // skip for non color management
    if (!renderEngineFactory->useColorManagement()) {
        return;
    }
    // skip for GLESRenderEngine
    if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) {
        return;
    }

    initializeRenderEngine();
    fillBufferColorTransformAndSourceDataspace<ColorSourceVariant>();
}

TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransform_outputDataspace) {
    const auto& renderEngineFactory = GetParam();
    // skip for non color management
    if (!renderEngineFactory->useColorManagement()) {
        return;
    }
    // skip for GLESRenderEngine
    if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) {
        return;
    }

    initializeRenderEngine();
    fillBufferColorTransformAndOutputDataspace<ColorSourceVariant>();
}

TEST_P(RenderEngineTest, drawLayers_fillBufferRoundedCorners_colorSource) {
    initializeRenderEngine();
    fillBufferWithRoundedCorners<ColorSourceVariant>();
@@ -1507,6 +1641,36 @@ TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransform_opaqueBufferSource)
    fillBufferColorTransform<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}

TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransformAndSourceDataspace_opaqueBufferSource) {
    const auto& renderEngineFactory = GetParam();
    // skip for non color management
    if (!renderEngineFactory->useColorManagement()) {
        return;
    }
    // skip for GLESRenderEngine
    if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) {
        return;
    }

    initializeRenderEngine();
    fillBufferColorTransformAndSourceDataspace<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}

TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransformAndOutputDataspace_opaqueBufferSource) {
    const auto& renderEngineFactory = GetParam();
    // skip for non color management
    if (!renderEngineFactory->useColorManagement()) {
        return;
    }
    // skip for GLESRenderEngine
    if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) {
        return;
    }

    initializeRenderEngine();
    fillBufferColorTransformAndOutputDataspace<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}

TEST_P(RenderEngineTest, drawLayers_fillBufferRoundedCorners_opaqueBufferSource) {
    initializeRenderEngine();
    fillBufferWithRoundedCorners<BufferSourceVariant<ForceOpaqueBufferVariant>>();
@@ -1587,6 +1751,36 @@ TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransform_bufferSource) {
    fillBufferColorTransform<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}

TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransformAndSourceDataspace_bufferSource) {
    const auto& renderEngineFactory = GetParam();
    // skip for non color management
    if (!renderEngineFactory->useColorManagement()) {
        return;
    }
    // skip for GLESRenderEngine
    if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) {
        return;
    }

    initializeRenderEngine();
    fillBufferColorTransformAndSourceDataspace<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}

TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransformAndOutputDataspace_bufferSource) {
    const auto& renderEngineFactory = GetParam();
    // skip for non color management
    if (!renderEngineFactory->useColorManagement()) {
        return;
    }
    // skip for GLESRenderEngine
    if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) {
        return;
    }

    initializeRenderEngine();
    fillBufferColorTransformAndOutputDataspace<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}

TEST_P(RenderEngineTest, drawLayers_fillBufferRoundedCorners_bufferSource) {
    initializeRenderEngine();
    fillBufferWithRoundedCorners<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+140 −4
Original line number Diff line number Diff line
@@ -72,6 +72,70 @@ static void generateEOTF(ui::Dataspace dataspace, std::string& shader) {
                }
            )");
            break;
        case HAL_DATASPACE_TRANSFER_SMPTE_170M:
            shader.append(R"(

                float EOTF_sRGB(float srgb) {
                    return srgb <= 0.08125 ? srgb / 4.50 : pow((srgb + 0.099) / 1.099, 0.45);
                }

                float3 EOTF_sRGB(float3 srgb) {
                    return float3(EOTF_sRGB(srgb.r), EOTF_sRGB(srgb.g), EOTF_sRGB(srgb.b));
                }

                float3 EOTF(float3 srgb) {
                    return sign(srgb.rgb) * EOTF_sRGB(abs(srgb.rgb));
                }
            )");
            break;
        case HAL_DATASPACE_TRANSFER_GAMMA2_2:
            shader.append(R"(

                float EOTF_sRGB(float srgb) {
                    return pow(srgb, 2.2);
                }

                float3 EOTF_sRGB(float3 srgb) {
                    return float3(EOTF_sRGB(srgb.r), EOTF_sRGB(srgb.g), EOTF_sRGB(srgb.b));
                }

                float3 EOTF(float3 srgb) {
                    return sign(srgb.rgb) * EOTF_sRGB(abs(srgb.rgb));
                }
            )");
            break;
        case HAL_DATASPACE_TRANSFER_GAMMA2_6:
            shader.append(R"(

                float EOTF_sRGB(float srgb) {
                    return pow(srgb, 2.6);
                }

                float3 EOTF_sRGB(float3 srgb) {
                    return float3(EOTF_sRGB(srgb.r), EOTF_sRGB(srgb.g), EOTF_sRGB(srgb.b));
                }

                float3 EOTF(float3 srgb) {
                    return sign(srgb.rgb) * EOTF_sRGB(abs(srgb.rgb));
                }
            )");
            break;
        case HAL_DATASPACE_TRANSFER_GAMMA2_8:
            shader.append(R"(

                float EOTF_sRGB(float srgb) {
                    return pow(srgb, 2.8);
                }

                float3 EOTF_sRGB(float3 srgb) {
                    return float3(EOTF_sRGB(srgb.r), EOTF_sRGB(srgb.g), EOTF_sRGB(srgb.b));
                }

                float3 EOTF(float3 srgb) {
                    return sign(srgb.rgb) * EOTF_sRGB(abs(srgb.rgb));
                }
            )");
            break;
        case HAL_DATASPACE_TRANSFER_SRGB:
        default:
            shader.append(R"(
@@ -239,6 +303,67 @@ static void generateOETF(ui::Dataspace dataspace, std::string& shader) {
                }
            )");
            break;
        case HAL_DATASPACE_TRANSFER_SMPTE_170M:
            shader.append(R"(
                float OETF_sRGB(float linear) {
                    return linear <= 0.018 ?
                            linear * 4.50 : (pow(linear, 0.45) * 1.099) - 0.099;
                }

                float3 OETF_sRGB(float3 linear) {
                    return float3(OETF_sRGB(linear.r), OETF_sRGB(linear.g), OETF_sRGB(linear.b));
                }

                float3 OETF(float3 linear) {
                    return sign(linear.rgb) * OETF_sRGB(abs(linear.rgb));
                }
            )");
            break;
        case HAL_DATASPACE_TRANSFER_GAMMA2_2:
            shader.append(R"(
                float OETF_sRGB(float linear) {
                    return pow(linear, (1.0 / 2.2));
                }

                float3 OETF_sRGB(float3 linear) {
                    return float3(OETF_sRGB(linear.r), OETF_sRGB(linear.g), OETF_sRGB(linear.b));
                }

                float3 OETF(float3 linear) {
                    return sign(linear.rgb) * OETF_sRGB(abs(linear.rgb));
                }
            )");
            break;
        case HAL_DATASPACE_TRANSFER_GAMMA2_6:
            shader.append(R"(
                float OETF_sRGB(float linear) {
                    return pow(linear, (1.0 / 2.6));
                }

                float3 OETF_sRGB(float3 linear) {
                    return float3(OETF_sRGB(linear.r), OETF_sRGB(linear.g), OETF_sRGB(linear.b));
                }

                float3 OETF(float3 linear) {
                    return sign(linear.rgb) * OETF_sRGB(abs(linear.rgb));
                }
            )");
            break;
        case HAL_DATASPACE_TRANSFER_GAMMA2_8:
            shader.append(R"(
                float OETF_sRGB(float linear) {
                    return pow(linear, (1.0 / 2.8));
                }

                float3 OETF_sRGB(float3 linear) {
                    return float3(OETF_sRGB(linear.r), OETF_sRGB(linear.g), OETF_sRGB(linear.b));
                }

                float3 OETF(float3 linear) {
                    return sign(linear.rgb) * OETF_sRGB(abs(linear.rgb));
                }
            )");
            break;
        case HAL_DATASPACE_TRANSFER_SRGB:
        default:
            shader.append(R"(
@@ -285,20 +410,31 @@ static void generateEffectiveOOTF(bool undoPremultipliedAlpha, std::string& shad
        }
    )");
}

// please keep in sync with toSkColorSpace function in renderengine/skia/ColorSpaces.cpp
static ColorSpace toColorSpace(ui::Dataspace dataspace) {
    switch (dataspace & HAL_DATASPACE_STANDARD_MASK) {
        case HAL_DATASPACE_STANDARD_BT709:
            return ColorSpace::sRGB();
            break;
        case HAL_DATASPACE_STANDARD_DCI_P3:
            return ColorSpace::DisplayP3();
            break;
        case HAL_DATASPACE_STANDARD_BT2020:
        case HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE:
            return ColorSpace::BT2020();
            break;
        case HAL_DATASPACE_STANDARD_ADOBE_RGB:
            return ColorSpace::AdobeRGB();
        // TODO(b/208290320): BT601 format and variants return different primaries
        case HAL_DATASPACE_STANDARD_BT601_625:
        case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED:
        case HAL_DATASPACE_STANDARD_BT601_525:
        case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED:
        // TODO(b/208290329): BT407M format returns different primaries
        case HAL_DATASPACE_STANDARD_BT470M:
        // TODO(b/208290904): FILM format returns different primaries
        case HAL_DATASPACE_STANDARD_FILM:
        case HAL_DATASPACE_STANDARD_UNSPECIFIED:
        default:
            return ColorSpace::sRGB();
            break;
    }
}