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

Commit a247df04 authored by Romain Guy's avatar Romain Guy Committed by Android (Google) Code Review
Browse files

Merge "Pre-multiply gradient colors the right way"

parents be53bbba a0ed6f03
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -38,13 +38,13 @@ struct FloatColor {
    }

    // "color" is a gamma-encoded sRGB color
    // After calling this method, the color is stored as a pre-multiplied linear color
    // if linear blending is enabled.
    void setSRGB(uint32_t color) {
    // After calling this method, the color is stored as a linear color. The color
    // is not pre-multiplied.
    void setUnPreMultipliedSRGB(uint32_t color) {
        a = ((color >> 24) & 0xff) / 255.0f;
        r = a * EOCF_sRGB(((color >> 16) & 0xff) / 255.0f);
        g = a * EOCF_sRGB(((color >>  8) & 0xff) / 255.0f);
        b = a * EOCF_sRGB(((color      ) & 0xff) / 255.0f);
        r = EOCF_sRGB(((color >> 16) & 0xff) / 255.0f);
        g = EOCF_sRGB(((color >>  8) & 0xff) / 255.0f);
        b = EOCF_sRGB(((color      ) & 0xff) / 255.0f);
    }

    bool isNotBlack() {
+21 −16
Original line number Diff line number Diff line
@@ -188,26 +188,28 @@ size_t GradientCache::sourceBytesPerPixel() const {
void GradientCache::mixBytes(const FloatColor& start, const FloatColor& end,
        float amount, uint8_t*& dst) const {
    float oppAmount = 1.0f - amount;
    *dst++ = uint8_t(OECF_sRGB(start.r * oppAmount + end.r * amount) * 255.0f);
    *dst++ = uint8_t(OECF_sRGB(start.g * oppAmount + end.g * amount) * 255.0f);
    *dst++ = uint8_t(OECF_sRGB(start.b * oppAmount + end.b * amount) * 255.0f);
    *dst++ = uint8_t(         (start.a * oppAmount + end.a * amount) * 255.0f);
    float a = start.a * oppAmount + end.a * amount;
    *dst++ = uint8_t(a * OECF_sRGB((start.r * oppAmount + end.r * amount)) * 255.0f);
    *dst++ = uint8_t(a * OECF_sRGB((start.g * oppAmount + end.g * amount)) * 255.0f);
    *dst++ = uint8_t(a * OECF_sRGB((start.b * oppAmount + end.b * amount)) * 255.0f);
    *dst++ = uint8_t(a * 255.0f);
}

void GradientCache::mixFloats(const FloatColor& start, const FloatColor& end,
        float amount, uint8_t*& dst) const {
    float oppAmount = 1.0f - amount;
    float a = start.a * oppAmount + end.a * amount;
    float* d = (float*) dst;
#ifdef ANDROID_ENABLE_LINEAR_BLENDING
    *d++ = start.r * oppAmount + end.r * amount;
    *d++ = start.g * oppAmount + end.g * amount;
    *d++ = start.b * oppAmount + end.b * amount;
    *d++ = a * (start.r * oppAmount + end.r * amount);
    *d++ = a * (start.g * oppAmount + end.g * amount);
    *d++ = a * (start.b * oppAmount + end.b * amount);
#else
    *d++ = OECF_sRGB(start.r * oppAmount + end.r * amount);
    *d++ = OECF_sRGB(start.g * oppAmount + end.g * amount);
    *d++ = OECF_sRGB(start.b * oppAmount + end.b * amount);
    *d++ = a * OECF_sRGB(start.r * oppAmount + end.r * amount);
    *d++ = a * OECF_sRGB(start.g * oppAmount + end.g * amount);
    *d++ = a * OECF_sRGB(start.b * oppAmount + end.b * amount);
#endif
    *d++ = start.a * oppAmount + end.a * amount;
    *d++ = a;
    dst += 4 * sizeof(float);
}

@@ -217,16 +219,19 @@ void GradientCache::generateTexture(uint32_t* colors, float* positions,
    uint8_t pixels[rowBytes * height];

    static ChannelMixer gMixers[] = {
            &android::uirenderer::GradientCache::mixBytes,  // colors are stored gamma-encoded
            &android::uirenderer::GradientCache::mixFloats, // colors are stored in linear
            // colors are stored gamma-encoded
            &android::uirenderer::GradientCache::mixBytes,
            // colors are stored in linear (linear blending on)
            // or gamma-encoded (linear blending off)
            &android::uirenderer::GradientCache::mixFloats,
    };
    ChannelMixer mix = gMixers[mUseFloatTexture];

    FloatColor start;
    start.setSRGB(colors[0]);
    start.setUnPreMultipliedSRGB(colors[0]);

    FloatColor end;
    end.setSRGB(colors[1]);
    end.setUnPreMultipliedSRGB(colors[1]);

    int currentPos = 1;
    float startPos = positions[0];
@@ -241,7 +246,7 @@ void GradientCache::generateTexture(uint32_t* colors, float* positions,

            currentPos++;

            end.setSRGB(colors[currentPos]);
            end.setUnPreMultipliedSRGB(colors[currentPos]);
            distance = positions[currentPos] - startPos;
        }

+5 −3
Original line number Diff line number Diff line
@@ -175,10 +175,11 @@ const char* gFS_Gradient_Functions =
const char* gFS_Gradient_Preamble[2] = {
        // Linear framebuffer
        "\nvec4 dither(const vec4 color) {\n"
        "    return vec4(color.rgb + (triangleNoise(gl_FragCoord.xy * screenSize.xy) / 255.0), color.a);"
        "    return vec4(color.rgb + (triangleNoise(gl_FragCoord.xy * screenSize.xy) / 255.0), color.a);\n"
        "}\n"
        "\nvec4 gammaMix(const vec4 a, const vec4 b, float v) {\n"
        "    return pow(mix(a, b, v), vec4(vec3(1.0 / 2.2), 1.0));"
        "    vec4 c = pow(mix(a, b, v), vec4(vec3(1.0 / 2.2), 1.0));\n"
        "    return vec4(c.rgb * c.a, c.a);\n"
        "}\n",
        // sRGB framebuffer
        "\nvec4 dither(const vec4 color) {\n"
@@ -186,7 +187,8 @@ const char* gFS_Gradient_Preamble[2] = {
        "    return vec4(dithered * dithered, color.a);\n"
        "}\n"
        "\nvec4 gammaMix(const vec4 a, const vec4 b, float v) {\n"
        "    return mix(a, b, v);"
        "    vec4 c = mix(a, b, v);\n"
        "    return vec4(c.rgb * c.a, c.a);\n"
        "}\n"
};

+4 −4
Original line number Diff line number Diff line
@@ -81,7 +81,7 @@ static void computeScreenSpaceMatrix(mat4& screenSpace, const SkMatrix& unitMatr
}

///////////////////////////////////////////////////////////////////////////////
// gradient shader matrix helpers
// Gradient shader matrix helpers
///////////////////////////////////////////////////////////////////////////////

static void toLinearUnitMatrix(const SkPoint pts[2], SkMatrix* matrix) {
@@ -161,7 +161,7 @@ bool tryStoreGradient(Caches& caches, const SkShader& shader, const Matrix4 mode
    gradInfo.fColorOffsets = &colorOffsets[0];
    shader.asAGradient(&gradInfo);

    if (CC_UNLIKELY(!isSimpleGradient(gradInfo))) {
    if (CC_UNLIKELY(!description->isSimpleGradient)) {
        outData->gradientSampler = (*textureUnit)++;

#ifndef SK_SCALAR_IS_FLOAT
@@ -174,8 +174,8 @@ bool tryStoreGradient(Caches& caches, const SkShader& shader, const Matrix4 mode
        outData->gradientSampler = 0;
        outData->gradientTexture = nullptr;

        outData->startColor.setSRGB(gradInfo.fColors[0]);
        outData->endColor.setSRGB(gradInfo.fColors[1]);
        outData->startColor.setUnPreMultipliedSRGB(gradInfo.fColors[0]);
        outData->endColor.setUnPreMultipliedSRGB(gradInfo.fColors[1]);
    }

    return true;