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

/**************************************************************************************************
 *** This file was autogenerated from GrMixerEffect.fp; do not modify.
 **************************************************************************************************/
#ifndef GrMixerEffect_DEFINED
#define GrMixerEffect_DEFINED

#include "include/core/SkM44.h"
#include "include/core/SkTypes.h"

#include "src/gpu/GrFragmentProcessor.h"

class GrMixerEffect : public GrFragmentProcessor {
public:
    SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& in) const override {
        const SkPMColor4f inColor = ConstantOutputForConstantInput(this->childProcessor(0), in);
        const SkPMColor4f c0 = ConstantOutputForConstantInput(this->childProcessor(1), inColor);
        const SkPMColor4f c1 = ConstantOutputForConstantInput(this->childProcessor(2), inColor);
        return {c0.fR + (c1.fR - c0.fR) * weight, c0.fG + (c1.fG - c0.fG) * weight,
                c0.fB + (c1.fB - c0.fB) * weight, c0.fA + (c1.fA - c0.fA) * weight};
    }
    static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP,
                                                     std::unique_ptr<GrFragmentProcessor> fp0,
                                                     std::unique_ptr<GrFragmentProcessor> fp1,
                                                     float weight) {
        return std::unique_ptr<GrFragmentProcessor>(
                new GrMixerEffect(std::move(inputFP), std::move(fp0), std::move(fp1), weight));
    }
    GrMixerEffect(const GrMixerEffect& src);
    std::unique_ptr<GrFragmentProcessor> clone() const override;
    const char* name() const override { return "MixerEffect"; }
    bool usesExplicitReturn() const override;
    float weight;

private:
    GrMixerEffect(std::unique_ptr<GrFragmentProcessor> inputFP,
                  std::unique_ptr<GrFragmentProcessor> fp0,
                  std::unique_ptr<GrFragmentProcessor> fp1,
                  float weight)
            : INHERITED(kGrMixerEffect_ClassID,
                        (OptimizationFlags)ProcessorOptimizationFlags(inputFP.get()) &
                                ProcessorOptimizationFlags(fp1.get()) &
                                ProcessorOptimizationFlags(fp0.get()))
            , weight(weight) {
        this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
        SkASSERT(fp0);
        this->registerChild(std::move(fp0), SkSL::SampleUsage::PassThrough());
        this->registerChild(std::move(fp1), SkSL::SampleUsage::PassThrough());
    }
    GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
    void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
    bool onIsEqual(const GrFragmentProcessor&) const override;
#if GR_TEST_UTILS
    SkString onDumpInfo() const override;
#endif
    GR_DECLARE_FRAGMENT_PROCESSOR_TEST
    using INHERITED = GrFragmentProcessor;
};
#endif
