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

Commit acf8b73c authored by Michael Ludwig's avatar Michael Ludwig
Browse files

Update GainMap to assume it is rendering a linear surface

SkShaders return color values in the dst color space, so `sdr` and `hdr`
children of the gainmap return linear values if the gainmap is rendered
into a linear surface.

The gainmap shader could be made more flexible by wrapping it in a call
to SkShader::makeWithWorkingColorSpace(linear), but it is only used in
one place so I opted for documenting the requirements of the shader and
how either approach could work. Since the gainmap shader is the final
effect of the composition in the current usecase, using the dst
colorspace to handle conversion keeps things simplest.

Flag: EXEMPT bug fix
Bug: 426601394
Change-Id: I49596e6a161b509deaccbdc31dd2a342ef771862
parent ba8f28d7
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -1370,6 +1370,12 @@ void SkiaRenderEngine::tonemapAndDrawGainmapInternal(
    std::lock_guard<std::mutex> lock(mRenderingMutex);
    auto context = getActiveContext();
    auto gainmapTextureRef = getOrCreateBackendTexture(gainmap->getBuffer(), true);

    // The Dataspace used to create the SkSurface must be a linear colorspace in order to meet the
    // requirements for the gainmap shader. Since this is done via the dst colorspace and the shader
    // is painted into the surface directly, there is no need to wrap the gainmap shader with
    // `SkShader::makeWithWorkingColorSpace`. `hdrShader` and `sdrShader` will both output
    // values in the dst colorspace, which meets the linear gamma requirement.
    sk_sp<SkSurface> gainmapSurface =
            gainmapTextureRef->getOrCreateSurface(ui::Dataspace::V0_SRGB_LINEAR);

+4 −2
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@ namespace skia {
namespace {

// Please refer to https://developer.android.com/media/platform/hdr-image-format#gain_map-generation
// This shader assumes that it will be used in a linear gamma colorspace context, e.g. all values
// sampled from `sdr` and `hdr` are linear and it is outputting an encoded ratio of luminances.
static const SkString kGainmapShaderString = SkString(R"(
    uniform shader sdr;
    uniform shader hdr;
@@ -41,8 +43,8 @@ static const SkString kGainmapShaderString = SkString(R"(
    }

    vec4 main(vec2 xy) {
        float sdrY = luminance(toLinearSrgb(sdr.eval(xy).rgb));
        float hdrY = luminance(toLinearSrgb(hdr.eval(xy).rgb));
        float sdrY = luminance(sdr.eval(xy).rgb);
        float hdrY = luminance(hdr.eval(xy).rgb);
        float pixelGain = (hdrY + offsetHdr) / (sdrY + offsetSdr);
        float logRecovery = (log2(pixelGain) - mapMinLog2) / (mapMaxLog2 - mapMinLog2);
        return vec4(pow(clamp(logRecovery, 0.0, 1.0), mapGamma));