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

Commit 387b08fe authored by Sally Qi's avatar Sally Qi Committed by Android (Google) Code Review
Browse files

Merge "Enable more ColorSpaces in RenderEngine"

parents 39180c69 2019fd23
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;
    }
}