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

Commit 77c511c4 authored by Alec Mouri's avatar Alec Mouri
Browse files

Support per-layer color transforms when local tonemapping

* Preserve alpha channel when tonemapping
* Don't tonemap when a layer is entirely SDR

Bug: 329464641
Flag: com.android.graphics.surfaceflinger.flags.local_tonemap_screenshots
Test: adb shell cmd color_display set-layer-saturation 0 com.google.android.apps.wellbeing com.google.android.youtube
Change-Id: I363475caac5af83f2ef30bc073cf8c5aa6e313d4
parent 7f9f91a6
Loading
Loading
Loading
Loading
+25 −19
Original line number Diff line number Diff line
@@ -514,7 +514,7 @@ sk_sp<SkShader> SkiaRenderEngine::createRuntimeEffectShader(
    auto shader = parameters.shader;
    if (stretchEffect.hasEffect()) {
        const auto graphicBuffer = targetBuffer ? targetBuffer->getBuffer() : nullptr;
        if (graphicBuffer && parameters.shader) {
        if (graphicBuffer && shader) {
            shader = mStretchShaderFactory.createSkShader(shader, stretchEffect);
        }
    }
@@ -525,21 +525,25 @@ sk_sp<SkShader> SkiaRenderEngine::createRuntimeEffectShader(
                          static_cast<ui::PixelFormat>(targetBuffer->getPixelFormat()))
                : std::nullopt;

        if (parameters.display.tonemapStrategy == DisplaySettings::TonemapStrategy::Local) {
            // TODO: Handle color matrix transforms in linear space.
            SkImage* image = parameters.shader->isAImage((SkMatrix*)nullptr, (SkTileMode*)nullptr);
            if (image) {
        const auto hdrType = getHdrRenderType(parameters.layer.sourceDataspace, format);

        const auto usingLocalTonemap =
                parameters.display.tonemapStrategy == DisplaySettings::TonemapStrategy::Local &&
                hdrType != HdrRenderType::SDR &&
                shader->isAImage((SkMatrix*)nullptr, (SkTileMode*)nullptr);

        if (usingLocalTonemap) {
            static MouriMap kMapper;
                const float ratio = getHdrRenderType(parameters.layer.sourceDataspace, format) ==
                                HdrRenderType::GENERIC_HDR
                        ? 1.0f
                        : parameters.layerDimmingRatio;
                return kMapper.mouriMap(getActiveContext(), parameters.shader, ratio);
            }
            const float ratio =
                    hdrType == HdrRenderType::GENERIC_HDR ? 1.0f : parameters.layerDimmingRatio;
            shader = kMapper.mouriMap(getActiveContext(), shader, ratio);
        }

        // disable tonemapping if we already locally tonemapped
        auto inputDataspace =
                usingLocalTonemap ? parameters.outputDataSpace : parameters.layer.sourceDataspace;
        auto effect =
                shaders::LinearEffect{.inputDataspace = parameters.layer.sourceDataspace,
                shaders::LinearEffect{.inputDataspace = inputDataspace,
                                      .outputDataspace = parameters.outputDataSpace,
                                      .undoPremultipliedAlpha = parameters.undoPremultipliedAlpha,
                                      .fakeOutputDataspace = parameters.fakeOutputDataspace};
@@ -555,20 +559,22 @@ sk_sp<SkShader> SkiaRenderEngine::createRuntimeEffectShader(

        mat4 colorTransform = parameters.layer.colorTransform;

        if (!usingLocalTonemap) {
            colorTransform *=
                    mat4::scale(vec4(parameters.layerDimmingRatio, parameters.layerDimmingRatio,
                                     parameters.layerDimmingRatio, 1.f));
        }

        const auto targetBuffer = parameters.layer.source.buffer.buffer;
        const auto graphicBuffer = targetBuffer ? targetBuffer->getBuffer() : nullptr;
        const auto hardwareBuffer = graphicBuffer ? graphicBuffer->toAHardwareBuffer() : nullptr;
        return createLinearEffectShader(parameters.shader, effect, runtimeEffect,
                                        std::move(colorTransform), parameters.display.maxLuminance,
        return createLinearEffectShader(shader, effect, runtimeEffect, std::move(colorTransform),
                                        parameters.display.maxLuminance,
                                        parameters.display.currentLuminanceNits,
                                        parameters.layer.source.buffer.maxLuminanceNits,
                                        hardwareBuffer, parameters.display.renderIntent);
    }
    return parameters.shader;
    return shader;
}

void SkiaRenderEngine::initCanvas(SkCanvas* canvas, const DisplaySettings& display) {
+2 −2
Original line number Diff line number Diff line
@@ -84,13 +84,13 @@ const SkString kTonemap(R"(
        float3 linear = toLinearSrgb(rgba.rgb) * hdrSdrRatio;

        if (localMax <= 1.0) {
            return float4(fromLinearSrgb(linear), 1.0);
            return float4(fromLinearSrgb(linear), rgba.a);
        }

        float maxRGB = max(linear.r, max(linear.g, linear.b));
        localMax = max(localMax, maxRGB);
        float gain = (1 + maxRGB / (localMax * localMax)) / (1 + maxRGB);
        return float4(fromLinearSrgb(linear * gain), 1.0);
        return float4(fromLinearSrgb(linear * gain), rgba.a);
    }
)");