/*
 * Copyright 2019 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

in fragmentProcessor? inputFP;
layout(ctype=SkM44, tracked) in uniform half4x4 m;
layout(ctype=SkV4, tracked) in uniform half4 v;
layout(key) in bool unpremulInput;
layout(key) in bool clampRGBOutput;
layout(key) in bool premulOutput;

@optimizationFlags {
    (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) &
    kConstantOutputForConstantInput_OptimizationFlag
}

void main() {
    half4 inputColor = sample(inputFP, sk_InColor);
    @if (unpremulInput) {
        inputColor = unpremul(inputColor);
    }
    sk_OutColor = m * inputColor + v;
    @if (clampRGBOutput) {
        sk_OutColor = saturate(sk_OutColor);
    } else {
        sk_OutColor.a = saturate(sk_OutColor.a);
    }
    @if (premulOutput) {
        sk_OutColor.rgb *= sk_OutColor.a;
    }
}

@class {
    SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
        SkPMColor4f input = this->numChildProcessors()
                            ? ConstantOutputForConstantInput(this->childProcessor(0), inColor)
                            : inColor;
        SkColor4f color;
        if (unpremulInput) {
            color = input.unpremul();
        } else {
            color.fR = input.fR;
            color.fG = input.fG;
            color.fB = input.fB;
            color.fA = input.fA;
        }
        auto v4 = m.map(color.fR, color.fG, color.fB, color.fA) + v;
        color = {v4.x, v4.y, v4.z, v4.w};
        color.fA = SkTPin(color.fA, 0.f, 1.f);
        if (clampRGBOutput) {
            color.fR = SkTPin(color.fR, 0.f, 1.f);
            color.fG = SkTPin(color.fG, 0.f, 1.f);
            color.fB = SkTPin(color.fB, 0.f, 1.f);
        }
        if (premulOutput) {
            return color.premul();
        } else {
            return {color.fR, color.fG, color.fB, color.fA};
        }
    }
}

@make {
    static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP,
                                                     const float matrix[20], bool unpremulInput,
                                                     bool clampRGBOutput, bool premulOutput) {
        SkM44 m44(
            matrix[ 0], matrix[ 1], matrix[ 2], matrix[ 3],
            matrix[ 5], matrix[ 6], matrix[ 7], matrix[ 8],
            matrix[10], matrix[11], matrix[12], matrix[13],
            matrix[15], matrix[16], matrix[17], matrix[18]
        );
        SkV4 v4 = {matrix[4], matrix[9], matrix[14], matrix[19]};
        return std::unique_ptr<GrFragmentProcessor>(new GrColorMatrixFragmentProcessor(
            std::move(inputFP), m44, v4, unpremulInput, clampRGBOutput, premulOutput));
    }
}

@test(d) {
    float m[20];
    for (int i = 0; i < 20; ++i) {
        m[i] = d->fRandom->nextRangeScalar(-10.f, 10.f);
    }
    bool unpremul = d->fRandom->nextBool();
    bool clampRGB = d->fRandom->nextBool();
    bool premul = d->fRandom->nextBool();
    return Make(/*inputFP=*/nullptr, m, unpremul, clampRGB, premul);
}
