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

#include "src/gpu/effects/GrBlendFragmentProcessor.h"

#include "src/gpu/GrFragmentProcessor.h"
#include "src/gpu/SkGr.h"
#include "src/gpu/glsl/GrGLSLBlend.h"
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"

using GrBlendFragmentProcessor::BlendBehavior;

// Some of the cpu implementations of blend modes differ too much from the GPU enough that
// we can't use the cpu implementation to implement constantOutputForConstantInput.
static inline bool does_cpu_blend_impl_match_gpu(SkBlendMode mode) {
    // The non-seperable modes differ too much. So does SoftLight. ColorBurn differs too much on our
    // test iOS device (but we just disable it across the aboard since it may happen on untested
    // GPUs).
    return mode <= SkBlendMode::kLastSeparableMode && mode != SkBlendMode::kSoftLight &&
           mode != SkBlendMode::kColorBurn;
}

static const char* BlendBehavior_Name(BlendBehavior behavior) {
    SkASSERT(unsigned(behavior) <= unsigned(BlendBehavior::kLastBlendBehavior));
    static constexpr const char* gStrings[] = {
        "Default",
        "Compose-One",
        "Compose-Two",
        "SkMode",
    };
    static_assert(SK_ARRAY_COUNT(gStrings) == size_t(BlendBehavior::kLastBlendBehavior) + 1);
    return gStrings[int(behavior)];
}

//////////////////////////////////////////////////////////////////////////////

class BlendFragmentProcessor : public GrFragmentProcessor {
public:
    static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> src,
                                                     std::unique_ptr<GrFragmentProcessor> dst,
                                                     SkBlendMode mode, BlendBehavior behavior) {
        return std::unique_ptr<GrFragmentProcessor>(
                new BlendFragmentProcessor(std::move(src), std::move(dst), mode, behavior));
    }

    const char* name() const override { return "Blend"; }

    std::unique_ptr<GrFragmentProcessor> clone() const override;

    SkBlendMode getMode() const { return fMode; }
    BlendBehavior blendBehavior() const { return fBlendBehavior; }

private:
    BlendFragmentProcessor(std::unique_ptr<GrFragmentProcessor> src,
                             std::unique_ptr<GrFragmentProcessor> dst,
                             SkBlendMode mode, BlendBehavior behavior)
            : INHERITED(kBlendFragmentProcessor_ClassID, OptFlags(src.get(), dst.get(), mode))
            , fMode(mode)
            , fBlendBehavior(behavior) {
        if (fBlendBehavior == BlendBehavior::kDefault) {
            fBlendBehavior = (src && dst) ? BlendBehavior::kComposeTwoBehavior
                                          : BlendBehavior::kComposeOneBehavior;
        }
        this->registerChild(std::move(src));
        this->registerChild(std::move(dst));
    }

    BlendFragmentProcessor(const BlendFragmentProcessor& that)
            : INHERITED(kBlendFragmentProcessor_ClassID, ProcessorOptimizationFlags(&that))
            , fMode(that.fMode)
            , fBlendBehavior(that.fBlendBehavior) {
        this->cloneAndRegisterAllChildProcessors(that);
    }

#if GR_TEST_UTILS
    SkString onDumpInfo() const override {
        return SkStringPrintf("(fMode=%s)", SkBlendMode_Name(fMode));
    }
#endif

    static OptimizationFlags OptFlags(const GrFragmentProcessor* src,
                                      const GrFragmentProcessor* dst, SkBlendMode mode) {
        OptimizationFlags flags;
        switch (mode) {
            case SkBlendMode::kClear:
            case SkBlendMode::kSrc:
            case SkBlendMode::kDst:
                SK_ABORT("Shouldn't have created a Blend FP as 'clear', 'src', or 'dst'.");
                flags = kNone_OptimizationFlags;
                break;

            // Produces opaque if both src and dst are opaque. These also will modulate the child's
            // output by either the input color or alpha. However, if the child is not compatible
            // with the coverage as alpha then it may produce a color that is not valid premul.
            case SkBlendMode::kSrcIn:
            case SkBlendMode::kDstIn:
            case SkBlendMode::kModulate:
                if (src && dst) {
                    flags = ProcessorOptimizationFlags(src) & ProcessorOptimizationFlags(dst) &
                            kPreservesOpaqueInput_OptimizationFlag;
                } else if (src) {
                    flags = ProcessorOptimizationFlags(src) &
                            ~kConstantOutputForConstantInput_OptimizationFlag;
                } else if (dst) {
                    flags = ProcessorOptimizationFlags(dst) &
                            ~kConstantOutputForConstantInput_OptimizationFlag;
                } else {
                    flags = kNone_OptimizationFlags;
                }
                break;

            // Produces zero when both are opaque, indeterminate if one is opaque.
            case SkBlendMode::kSrcOut:
            case SkBlendMode::kDstOut:
            case SkBlendMode::kXor:
                flags = kNone_OptimizationFlags;
                break;

            // Is opaque if the dst is opaque.
            case SkBlendMode::kSrcATop:
                flags = ProcessorOptimizationFlags(dst) & kPreservesOpaqueInput_OptimizationFlag;
                break;

            // DstATop is the converse of kSrcATop. Screen is also opaque if the src is a opaque.
            case SkBlendMode::kDstATop:
            case SkBlendMode::kScreen:
                flags = ProcessorOptimizationFlags(src) & kPreservesOpaqueInput_OptimizationFlag;
                break;

            // These modes are all opaque if either src or dst is opaque. All the advanced modes
            // compute alpha as src-over.
            case SkBlendMode::kSrcOver:
            case SkBlendMode::kDstOver:
            case SkBlendMode::kPlus:
            case SkBlendMode::kOverlay:
            case SkBlendMode::kDarken:
            case SkBlendMode::kLighten:
            case SkBlendMode::kColorDodge:
            case SkBlendMode::kColorBurn:
            case SkBlendMode::kHardLight:
            case SkBlendMode::kSoftLight:
            case SkBlendMode::kDifference:
            case SkBlendMode::kExclusion:
            case SkBlendMode::kMultiply:
            case SkBlendMode::kHue:
            case SkBlendMode::kSaturation:
            case SkBlendMode::kColor:
            case SkBlendMode::kLuminosity:
                flags = (ProcessorOptimizationFlags(src) | ProcessorOptimizationFlags(dst)) &
                        kPreservesOpaqueInput_OptimizationFlag;
                break;
        }
        if (does_cpu_blend_impl_match_gpu(mode) &&
            (src ? src->hasConstantOutputForConstantInput() : true) &&
            (dst ? dst->hasConstantOutputForConstantInput() : true)) {
            flags |= kConstantOutputForConstantInput_OptimizationFlag;
        }
        return flags;
    }

    void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
        b->add32((int)fMode);
    }

    bool onIsEqual(const GrFragmentProcessor& other) const override {
        const BlendFragmentProcessor& cs = other.cast<BlendFragmentProcessor>();
        return fMode == cs.fMode;
    }

    SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
        const auto* src = this->childProcessor(0);
        const auto* dst = this->childProcessor(1);

        switch (fBlendBehavior) {
            case BlendBehavior::kComposeOneBehavior: {
                SkPMColor4f srcColor = src ? ConstantOutputForConstantInput(src, SK_PMColor4fWHITE)
                                           : input;
                SkPMColor4f dstColor = dst ? ConstantOutputForConstantInput(dst, SK_PMColor4fWHITE)
                                           : input;
                return SkBlendMode_Apply(fMode, srcColor, dstColor);
            }

            case BlendBehavior::kComposeTwoBehavior: {
                SkPMColor4f opaqueInput = { input.fR, input.fG, input.fB, 1 };
                SkPMColor4f srcColor = ConstantOutputForConstantInput(src, opaqueInput);
                SkPMColor4f dstColor = ConstantOutputForConstantInput(dst, opaqueInput);
                SkPMColor4f result = SkBlendMode_Apply(fMode, srcColor, dstColor);
                return result * input.fA;
            }

            case BlendBehavior::kSkModeBehavior: {
                SkPMColor4f srcColor = src ? ConstantOutputForConstantInput(src, SK_PMColor4fWHITE)
                                           : input;
                SkPMColor4f dstColor = dst ? ConstantOutputForConstantInput(dst, input)
                                           : input;
                return SkBlendMode_Apply(fMode, srcColor, dstColor);
            }

            default:
                SK_ABORT("unrecognized blend behavior");
                return input;
        }
    }

    std::unique_ptr<GrGLSLFragmentProcessor> onMakeProgramImpl() const override;

    SkBlendMode fMode;
    BlendBehavior fBlendBehavior;

    GR_DECLARE_FRAGMENT_PROCESSOR_TEST

    using INHERITED = GrFragmentProcessor;
};

/////////////////////////////////////////////////////////////////////

class GLBlendFragmentProcessor : public GrGLSLFragmentProcessor {
public:
    void emitCode(EmitArgs&) override;

private:
    using INHERITED = GrGLSLFragmentProcessor;
};

/////////////////////////////////////////////////////////////////////

GR_DEFINE_FRAGMENT_PROCESSOR_TEST(BlendFragmentProcessor);

#if GR_TEST_UTILS
std::unique_ptr<GrFragmentProcessor> BlendFragmentProcessor::TestCreate(GrProcessorTestData* d) {
    // Create one or two random fragment processors.
    std::unique_ptr<GrFragmentProcessor> src(GrProcessorUnitTest::MakeOptionalChildFP(d));
    std::unique_ptr<GrFragmentProcessor> dst(GrProcessorUnitTest::MakeChildFP(d));
    if (d->fRandom->nextBool()) {
        std::swap(src, dst);
    }

    SkBlendMode mode;
    BlendBehavior behavior;
    do {
        mode = static_cast<SkBlendMode>(d->fRandom->nextRangeU(0, (int)SkBlendMode::kLastMode));
        behavior = static_cast<BlendBehavior>(
                d->fRandom->nextRangeU(0, (int)BlendBehavior::kLastBlendBehavior));
    } while (SkBlendMode::kClear == mode || SkBlendMode::kSrc == mode || SkBlendMode::kDst == mode);
    return std::unique_ptr<GrFragmentProcessor>(
            new BlendFragmentProcessor(std::move(src), std::move(dst), mode, behavior));
}
#endif

std::unique_ptr<GrFragmentProcessor> BlendFragmentProcessor::clone() const {
    return std::unique_ptr<GrFragmentProcessor>(new BlendFragmentProcessor(*this));
}

std::unique_ptr<GrGLSLFragmentProcessor> BlendFragmentProcessor::onMakeProgramImpl() const {
    return std::make_unique<GLBlendFragmentProcessor>();
}

/////////////////////////////////////////////////////////////////////

void GLBlendFragmentProcessor::emitCode(EmitArgs& args) {
    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
    const BlendFragmentProcessor& cs = args.fFp.cast<BlendFragmentProcessor>();
    SkBlendMode mode = cs.getMode();
    BlendBehavior behavior = cs.blendBehavior();

    // Load the input color and make an opaque copy if needed.
    fragBuilder->codeAppendf("// Blend mode: %s (%s behavior)\n",
                             SkBlendMode_Name(mode), BlendBehavior_Name(behavior));

    SkString srcColor, dstColor;
    switch (behavior) {
        case BlendBehavior::kComposeOneBehavior:
            // Compose-one operations historically leave the alpha on the input color.
            srcColor = cs.childProcessor(0) ? this->invokeChild(0, "half4(1)", args)
                                            : SkString(args.fInputColor);
            dstColor = cs.childProcessor(1) ? this->invokeChild(1, "half4(1)", args)
                                            : SkString(args.fInputColor);
            break;

        case BlendBehavior::kComposeTwoBehavior:
            // Compose-two operations historically have forced the input color to opaque.
            // We're going to re-apply the input color's alpha below, so feed the *unpremul* RGB
            // to the children, to avoid double-applying alpha.
            fragBuilder->codeAppendf("half4 inputOpaque = unpremul(%s).rgb1;\n", args.fInputColor);
            srcColor = this->invokeChild(0, "inputOpaque", args);
            dstColor = this->invokeChild(1, "inputOpaque", args);
            break;

        case BlendBehavior::kSkModeBehavior:
            // SkModeColorFilter operations act like ComposeOne, but pass the input color to dst.
            srcColor = cs.childProcessor(0) ? this->invokeChild(0, "half4(1)", args)
                                            : SkString(args.fInputColor);
            dstColor = cs.childProcessor(1) ? this->invokeChild(1, args.fInputColor, args)
                                            : SkString(args.fInputColor);
            break;

        default:
            SK_ABORT("unrecognized blend behavior");
            break;
    }

    // Blend src and dst colors together.
    fragBuilder->codeAppendf("return %s(%s, %s)", GrGLSLBlend::BlendFuncName(mode),
                             srcColor.c_str(), dstColor.c_str());

    // Reapply alpha from input color if we are doing a compose-two.
    if (behavior == BlendBehavior::kComposeTwoBehavior) {
        fragBuilder->codeAppendf(" * %s.a", args.fInputColor);
    }

    fragBuilder->codeAppendf(";\n");
}

//////////////////////////////////////////////////////////////////////////////

std::unique_ptr<GrFragmentProcessor> GrBlendFragmentProcessor::Make(
        std::unique_ptr<GrFragmentProcessor> src,
        std::unique_ptr<GrFragmentProcessor> dst,
        SkBlendMode mode, BlendBehavior behavior) {
    switch (mode) {
        case SkBlendMode::kClear:
            return GrFragmentProcessor::MakeColor(SK_PMColor4fTRANSPARENT);
        case SkBlendMode::kSrc:
            return GrFragmentProcessor::OverrideInput(std::move(src), SK_PMColor4fWHITE,
                                                      /*useUniform=*/false);
        case SkBlendMode::kDst:
            return GrFragmentProcessor::OverrideInput(std::move(dst), SK_PMColor4fWHITE,
                                                      /*useUniform=*/false);
        default:
            return BlendFragmentProcessor::Make(std::move(src), std::move(dst), mode, behavior);
    }
}
