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

#ifndef GrFragmentProcessor_DEFINED
#define GrFragmentProcessor_DEFINED

#include "include/private/SkMacros.h"
#include "include/private/SkSLSampleUsage.h"
#include "include/private/SkSLString.h"
#include "src/gpu/ganesh/GrProcessor.h"
#include "src/gpu/ganesh/glsl/GrGLSLUniformHandler.h"

#include <tuple>

class GrGLSLFPFragmentBuilder;
class GrGLSLProgramDataManager;
class GrPaint;
class GrPipeline;
struct GrShaderCaps;
class GrTextureEffect;

namespace skgpu {
class KeyBuilder;
class Swizzle;
}

/**
 * Some fragment-processor creation methods have preconditions that might not be satisfied by the
 * calling code. Those methods can return a `GrFPResult` from their factory methods. If creation
 * succeeds, the new fragment processor is created and `success` is true. If a precondition is not
 * met, `success` is set to false and the input FP is returned unchanged.
 */
class GrFragmentProcessor;
using GrFPResult = std::tuple<bool /*success*/, std::unique_ptr<GrFragmentProcessor>>;

/** Provides custom fragment shader code. Fragment processors receive an input position and
    produce an output color. They may contain uniforms and may have children fragment processors
    that are sampled.
 */
class GrFragmentProcessor : public GrProcessor {
public:
    /**
     * Every GrFragmentProcessor must be capable of creating a subclass of ProgramImpl. The
     * ProgramImpl emits the fragment shader code that implements the GrFragmentProcessor, is
     * attached to the generated backend API pipeline/program and used to extract uniform data from
     * GrFragmentProcessor instances.
     */
    class ProgramImpl;

    /** Always returns 'color'. */
    static std::unique_ptr<GrFragmentProcessor> MakeColor(SkPMColor4f color);

    /**
     *  Returns the input color, modulated by the child's alpha.
     *
     *  output = input * child.a
     */
    static std::unique_ptr<GrFragmentProcessor> MulInputByChildAlpha(
            std::unique_ptr<GrFragmentProcessor> child);

    /**
     *  Invokes child with an opaque version of the input color, then applies the input alpha to
     *  the result. Used to incorporate paint alpha to the evaluation of an SkShader tree FP.
     */
    static std::unique_ptr<GrFragmentProcessor> ApplyPaintAlpha(
            std::unique_ptr<GrFragmentProcessor> child);

    /**
     *  Returns a fragment processor that generates the passed-in color, modulated by the child's
     *  RGBA color. The child's input color will be the parent's fInputColor. (Pass a null FP to use
     *  the color from fInputColor instead of a child FP.)
     */
    static std::unique_ptr<GrFragmentProcessor> ModulateRGBA(
            std::unique_ptr<GrFragmentProcessor> child, const SkPMColor4f& color);

    /**
     *  Returns a parent fragment processor that adopts the passed fragment processor as a child.
     *  The parent will ignore its input color and instead feed the passed in color as input to the
     *  child.
     */
    static std::unique_ptr<GrFragmentProcessor> OverrideInput(std::unique_ptr<GrFragmentProcessor>,
                                                              const SkPMColor4f&);

    /**
     *  Returns a parent fragment processor that adopts the passed fragment processor as a child.
     *  The parent will simply return the child's color, but disable the coverage-as-alpha
     *  optimization.
     */
    static std::unique_ptr<GrFragmentProcessor> DisableCoverageAsAlpha(
            std::unique_ptr<GrFragmentProcessor>);

    /**
     *  Returns a fragment processor which samples the passed-in fragment processor using
     *  `args.fDestColor` as its input color. Pass a null FP to access `args.fDestColor` directly.
     *  (This is only meaningful in contexts like blenders, which use a source and dest color.)
     */
    static std::unique_ptr<GrFragmentProcessor> UseDestColorAsInput(
            std::unique_ptr<GrFragmentProcessor>);

    /**
     *  Returns a fragment processor that calls the passed in fragment processor, and then swizzles
     *  the output.
     */
    static std::unique_ptr<GrFragmentProcessor> SwizzleOutput(std::unique_ptr<GrFragmentProcessor>,
                                                              const skgpu::Swizzle&);

    /**
     *  Returns a fragment processor that calls the passed in fragment processor, and then clamps
     *  the output to [0, 1].
     */
    static std::unique_ptr<GrFragmentProcessor> ClampOutput(std::unique_ptr<GrFragmentProcessor>);

    /**
     * Returns a fragment processor that composes two fragment processors `f` and `g` into f(g(x)).
     * This is equivalent to running them in series (`g`, then `f`). This is not the same as
     * transfer-mode composition; there is no blending step.
     */
    static std::unique_ptr<GrFragmentProcessor> Compose(std::unique_ptr<GrFragmentProcessor> f,
                                                        std::unique_ptr<GrFragmentProcessor> g);

    /*
     * Returns a fragment processor that calls the passed in fragment processor, then runs the
     * resulting color through the supplied color matrix.
     */
    static std::unique_ptr<GrFragmentProcessor> ColorMatrix(
            std::unique_ptr<GrFragmentProcessor> child,
            const float matrix[20],
            bool unpremulInput,
            bool clampRGBOutput,
            bool premulOutput);

    /**
     * Returns a fragment processor that reads back the color on the surface being painted; that is,
     * sampling this will return the color of the pixel that is currently being painted over.
     */
    static std::unique_ptr<GrFragmentProcessor> SurfaceColor();

    /**
     * Returns a fragment processor that calls the passed in fragment processor, but evaluates it
     * in device-space (rather than local space).
     */
    static std::unique_ptr<GrFragmentProcessor> DeviceSpace(std::unique_ptr<GrFragmentProcessor>);

    /**
     * "Shape" FPs, often used for clipping. Each one evaluates a particular kind of shape (rect,
     * circle, ellipse), and modulates the coverage of that shape against the results of the input
     * FP. GrClipEdgeType is used to select inverse/normal fill, and AA or non-AA edges.
     */
    static std::unique_ptr<GrFragmentProcessor> Rect(std::unique_ptr<GrFragmentProcessor>,
                                                     GrClipEdgeType,
                                                     SkRect);

    static GrFPResult Circle(std::unique_ptr<GrFragmentProcessor>,
                             GrClipEdgeType,
                             SkPoint center,
                             float radius);

    static GrFPResult Ellipse(std::unique_ptr<GrFragmentProcessor>,
                              GrClipEdgeType,
                              SkPoint center,
                              SkPoint radii,
                              const GrShaderCaps&);

    /**
     * Returns a fragment processor that calls the passed in fragment processor, but ensures the
     * entire program is compiled with high-precision types.
     */
    static std::unique_ptr<GrFragmentProcessor> HighPrecision(std::unique_ptr<GrFragmentProcessor>);

    /**
     * Makes a copy of this fragment processor that draws equivalently to the original.
     * If the processor has child processors they are cloned as well.
     */
    virtual std::unique_ptr<GrFragmentProcessor> clone() const = 0;

    // The FP this was registered with as a child function. This will be null if this is a root.
    const GrFragmentProcessor* parent() const { return fParent; }

    std::unique_ptr<ProgramImpl> makeProgramImpl() const;

    void addToKey(const GrShaderCaps& caps, skgpu::KeyBuilder* b) const {
        this->onAddToKey(caps, b);
        for (const auto& child : fChildProcessors) {
            if (child) {
                child->addToKey(caps, b);
            }
        }
    }

    int numChildProcessors() const { return fChildProcessors.count(); }
    int numNonNullChildProcessors() const;

    GrFragmentProcessor* childProcessor(int index) { return fChildProcessors[index].get(); }
    const GrFragmentProcessor* childProcessor(int index) const {
        return fChildProcessors[index].get();
    }

    SkDEBUGCODE(bool isInstantiated() const;)

    /** Do any of the FPs in this tree read back the color from the destination surface? */
    bool willReadDstColor() const {
        return SkToBool(fFlags & kWillReadDstColor_Flag);
    }

    /** Does the SkSL for this FP take two colors as its input arguments? */
    bool isBlendFunction() const {
        return SkToBool(fFlags & kIsBlendFunction_Flag);
    }

    /**
     * True if this FP refers directly to the sample coordinate parameter of its function
     * (e.g. uses EmitArgs::fSampleCoord in emitCode()). This is decided at FP-tree construction
     * time and is not affected by lifting coords to varyings.
     */
    bool usesSampleCoordsDirectly() const {
        return SkToBool(fFlags & kUsesSampleCoordsDirectly_Flag);
    }

    /**
     * True if this FP uses its input coordinates or if any descendant FP uses them through a chain
     * of non-explicit sample usages. (e.g. uses EmitArgs::fSampleCoord in emitCode()). This is
     * decided at FP-tree construction time and is not affected by lifting coords to varyings.
     */
    bool usesSampleCoords() const {
        return SkToBool(fFlags & (kUsesSampleCoordsDirectly_Flag |
                                  kUsesSampleCoordsIndirectly_Flag));
    }

    // The SampleUsage describing how this FP is invoked by its parent. This only reflects the
    // immediate sampling from parent to this FP.
    const SkSL::SampleUsage& sampleUsage() const {
        return fUsage;
    }

    /**
     * A GrDrawOp may premultiply its antialiasing coverage into its GrGeometryProcessor's color
     * output under the following scenario:
     *   * all the color fragment processors report true to this query,
     *   * all the coverage fragment processors report true to this query,
     *   * the blend mode arithmetic allows for it it.
     * To be compatible a fragment processor's output must be a modulation of its input color or
     * alpha with a computed premultiplied color or alpha that is in 0..1 range. The computed color
     * or alpha that is modulated against the input cannot depend on the input's alpha. The computed
     * value cannot depend on the input's color channels unless it unpremultiplies the input color
     * channels by the input alpha.
     */
    bool compatibleWithCoverageAsAlpha() const {
        return SkToBool(fFlags & kCompatibleWithCoverageAsAlpha_OptimizationFlag);
    }

    /**
     * If this is true then all opaque input colors to the processor produce opaque output colors.
     */
    bool preservesOpaqueInput() const {
        return SkToBool(fFlags & kPreservesOpaqueInput_OptimizationFlag);
    }

    /**
     * Tests whether given a constant input color the processor produces a constant output color
     * (for all fragments). If true outputColor will contain the constant color produces for
     * inputColor.
     */
    bool hasConstantOutputForConstantInput(SkPMColor4f inputColor, SkPMColor4f* outputColor) const {
        if (fFlags & kConstantOutputForConstantInput_OptimizationFlag) {
            *outputColor = this->constantOutputForConstantInput(inputColor);
            return true;
        }
        return false;
    }
    bool hasConstantOutputForConstantInput() const {
        return SkToBool(fFlags & kConstantOutputForConstantInput_OptimizationFlag);
    }

    /** Returns true if this and other processor conservatively draw identically. It can only return
        true when the two processor are of the same subclass (i.e. they return the same object from
        from getFactory()).

        A return value of true from isEqual() should not be used to test whether the processor would
        generate the same shader code. To test for identical code generation use addToKey.
     */
    bool isEqual(const GrFragmentProcessor& that) const;

    void visitProxies(const GrVisitProxyFunc&) const;

    void visitTextureEffects(const std::function<void(const GrTextureEffect&)>&) const;

    void visitWithImpls(const std::function<void(const GrFragmentProcessor&, ProgramImpl&)>&,
                        ProgramImpl&) const;

    GrTextureEffect* asTextureEffect();
    const GrTextureEffect* asTextureEffect() const;

#if GR_TEST_UTILS
    // Generates debug info for this processor tree by recursively calling dumpInfo() on this
    // processor and its children.
    SkString dumpTreeInfo() const;
#endif

protected:
    enum OptimizationFlags : uint32_t {
        kNone_OptimizationFlags,
        kCompatibleWithCoverageAsAlpha_OptimizationFlag = 0x1,
        kPreservesOpaqueInput_OptimizationFlag = 0x2,
        kConstantOutputForConstantInput_OptimizationFlag = 0x4,
        kAll_OptimizationFlags = kCompatibleWithCoverageAsAlpha_OptimizationFlag |
                                 kPreservesOpaqueInput_OptimizationFlag |
                                 kConstantOutputForConstantInput_OptimizationFlag
    };
    SK_DECL_BITFIELD_OPS_FRIENDS(OptimizationFlags)

    /**
     * Can be used as a helper to decide which fragment processor OptimizationFlags should be set.
     * This assumes that the subclass output color will be a modulation of the input color with a
     * value read from a texture of the passed color type and that the texture contains
     * premultiplied color or alpha values that are in range.
     *
     * Since there are multiple ways in which a sampler may have its coordinates clamped or wrapped,
     * callers must determine on their own if the sampling uses a decal strategy in any way, in
     * which case the texture may become transparent regardless of the color type.
     */
    static OptimizationFlags ModulateForSamplerOptFlags(SkAlphaType alphaType, bool samplingDecal) {
        if (samplingDecal) {
            return kCompatibleWithCoverageAsAlpha_OptimizationFlag;
        } else {
            return ModulateForClampedSamplerOptFlags(alphaType);
        }
    }

    // As above, but callers should somehow ensure or assert their sampler still uses clamping
    static OptimizationFlags ModulateForClampedSamplerOptFlags(SkAlphaType alphaType) {
        if (alphaType == kOpaque_SkAlphaType) {
            return kCompatibleWithCoverageAsAlpha_OptimizationFlag |
                   kPreservesOpaqueInput_OptimizationFlag;
        } else {
            return kCompatibleWithCoverageAsAlpha_OptimizationFlag;
        }
    }

    GrFragmentProcessor(ClassID classID, OptimizationFlags optimizationFlags)
            : INHERITED(classID), fFlags(optimizationFlags) {
        SkASSERT((optimizationFlags & ~kAll_OptimizationFlags) == 0);
    }

    explicit GrFragmentProcessor(const GrFragmentProcessor& src)
            : INHERITED(src.classID()), fFlags(src.fFlags) {
        this->cloneAndRegisterAllChildProcessors(src);
    }

    OptimizationFlags optimizationFlags() const {
        return static_cast<OptimizationFlags>(kAll_OptimizationFlags & fFlags);
    }

    /** Useful when you can't call fp->optimizationFlags() on a base class object from a subclass.*/
    static OptimizationFlags ProcessorOptimizationFlags(const GrFragmentProcessor* fp) {
        return fp ? fp->optimizationFlags() : kAll_OptimizationFlags;
    }

    /**
     * This allows one subclass to access another subclass's implementation of
     * constantOutputForConstantInput. It must only be called when
     * hasConstantOutputForConstantInput() is known to be true.
     */
    static SkPMColor4f ConstantOutputForConstantInput(const GrFragmentProcessor* fp,
                                                      const SkPMColor4f& input) {
        if (fp) {
            SkASSERT(fp->hasConstantOutputForConstantInput());
            return fp->constantOutputForConstantInput(input);
        } else {
            return input;
        }
    }

    /**
     * FragmentProcessor subclasses call this from their constructor to register any child
     * FragmentProcessors they have. This must be called AFTER all texture accesses and coord
     * transforms have been added.
     * This is for processors whose shader code will be composed of nested processors whose output
     * colors will be combined somehow to produce its output color. Registering these child
     * processors will allow the ProgramBuilder to automatically handle their transformed coords and
     * texture accesses and mangle their uniform and output color names.
     *
     * The SampleUsage parameter describes all of the ways that the child is sampled by the parent.
     */
    void registerChild(std::unique_ptr<GrFragmentProcessor> child,
                       SkSL::SampleUsage sampleUsage = SkSL::SampleUsage::PassThrough());

    /**
     * This method takes an existing fragment processor, clones all of its children, and registers
     * the clones as children of this fragment processor.
     */
    void cloneAndRegisterAllChildProcessors(const GrFragmentProcessor& src);

    // FP implementations must call this function if their matching ProgramImpl's emitCode()
    // function uses the EmitArgs::fSampleCoord variable in generated SkSL.
    void setUsesSampleCoordsDirectly() {
        fFlags |= kUsesSampleCoordsDirectly_Flag;
    }

    // FP implementations must set this flag if their ProgramImpl's emitCode() function calls
    // dstColor() to read back the framebuffer.
    void setWillReadDstColor() {
        fFlags |= kWillReadDstColor_Flag;
    }

    // FP implementations must set this flag if their ProgramImpl's emitCode() function emits a
    // blend function (taking two color inputs instead of just one).
    void setIsBlendFunction() {
        fFlags |= kIsBlendFunction_Flag;
    }

    void mergeOptimizationFlags(OptimizationFlags flags) {
        SkASSERT((flags & ~kAll_OptimizationFlags) == 0);
        fFlags &= (flags | ~kAll_OptimizationFlags);
    }

private:
    virtual SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& /* inputColor */) const {
        SK_ABORT("Subclass must override this if advertising this optimization.");
    }

    /**
     * Returns a new instance of the appropriate ProgramImpl subclass for the given
     * GrFragmentProcessor. It will emit the appropriate code and live with the cached program
     * to setup uniform data for each draw that uses the program.
     */
    virtual std::unique_ptr<ProgramImpl> onMakeProgramImpl() const = 0;

    virtual void onAddToKey(const GrShaderCaps&, skgpu::KeyBuilder*) const = 0;

    /**
     * Subclass implements this to support isEqual(). It will only be called if it is known that
     * the two processors are of the same subclass (i.e. have the same ClassID).
     */
    virtual bool onIsEqual(const GrFragmentProcessor&) const = 0;

    enum PrivateFlags {
        kFirstPrivateFlag = kAll_OptimizationFlags + 1,

        // Propagates up the FP tree to either root or first explicit sample usage.
        kUsesSampleCoordsIndirectly_Flag = kFirstPrivateFlag,

        // Does not propagate at all. It means this FP uses its input sample coords in some way.
        // Note passthrough and matrix sampling of children don't count as a usage of the coords.
        // Because indirect sampling stops at an explicit sample usage it is imperative that a FP
        // that calculates explicit coords for its children using its own sample coords sets this.
        kUsesSampleCoordsDirectly_Flag = kFirstPrivateFlag << 1,

        // Does not propagate at all.
        kIsBlendFunction_Flag = kFirstPrivateFlag << 2,

        // Propagates up the FP tree to the root.
        kWillReadDstColor_Flag = kFirstPrivateFlag << 3,
    };

    SkSTArray<1, std::unique_ptr<GrFragmentProcessor>, true> fChildProcessors;
    const GrFragmentProcessor* fParent = nullptr;
    uint32_t fFlags = 0;
    SkSL::SampleUsage fUsage;

    using INHERITED = GrProcessor;
};

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

class GrFragmentProcessor::ProgramImpl {
public:
    ProgramImpl() = default;

    virtual ~ProgramImpl() = default;

    using UniformHandle = GrGLSLUniformHandler::UniformHandle;
    using SamplerHandle = GrGLSLUniformHandler::SamplerHandle;

    /** Called when the program stage should insert its code into the shaders. The code in each
        shader will be in its own block ({}) and so locally scoped names will not collide across
        stages.

        @param fragBuilder       Interface used to emit code in the shaders.
        @param uniformHandler    Interface used for accessing information about our uniforms
        @param caps              The capabilities of the GPU which will render this FP
        @param fp                The processor that generated this program stage.
        @param inputColor        A half4 that holds the input color to the stage in the FS (or the
                                 source color, for blend processors). nullptr inputs are converted
                                 to "half4(1.0)" (solid white) during construction.
                                 TODO: Better system for communicating optimization info
                                 (e.g. input color is solid white, trans black, known to be opaque,
                                 etc.) that allows the processor to communicate back similar known
                                 info about its output.
        @param destColor         A half4 that holds the dest color to the stage. Only meaningful
                                 when the "is blend processor" FP flag is set.
        @param sampleCoord       The name of a local coord reference to a float2 variable. Only
                                 meaningful when the "references sample coords" FP flag is set.
     */
    struct EmitArgs {
        EmitArgs(GrGLSLFPFragmentBuilder* fragBuilder,
                 GrGLSLUniformHandler* uniformHandler,
                 const GrShaderCaps* caps,
                 const GrFragmentProcessor& fp,
                 const char* inputColor,
                 const char* destColor,
                 const char* sampleCoord)
                : fFragBuilder(fragBuilder)
                , fUniformHandler(uniformHandler)
                , fShaderCaps(caps)
                , fFp(fp)
                , fInputColor(inputColor ? inputColor : "half4(1.0)")
                , fDestColor(destColor)
                , fSampleCoord(sampleCoord) {}
        GrGLSLFPFragmentBuilder* fFragBuilder;
        GrGLSLUniformHandler* fUniformHandler;
        const GrShaderCaps* fShaderCaps;
        const GrFragmentProcessor& fFp;
        const char* fInputColor;
        const char* fDestColor;
        const char* fSampleCoord;
    };

    virtual void emitCode(EmitArgs&) = 0;

    // This does not recurse to any attached child processors. Recursing the entire processor tree
    // is the responsibility of the caller.
    void setData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor);

    int numChildProcessors() const { return fChildProcessors.count(); }

    ProgramImpl* childProcessor(int index) const { return fChildProcessors[index].get(); }

    void setFunctionName(SkString name) {
        SkASSERT(fFunctionName.isEmpty());
        fFunctionName = std::move(name);
    }

    const char* functionName() const {
        SkASSERT(!fFunctionName.isEmpty());
        return fFunctionName.c_str();
    }

    // Invoke the child with the default input and destination colors (solid white)
    inline SkString invokeChild(int childIndex,
                                EmitArgs& parentArgs,
                                std::string_view skslCoords = {}) {
        return this->invokeChild(childIndex,
                                 /*inputColor=*/nullptr,
                                 /*destColor=*/nullptr,
                                 parentArgs,
                                 skslCoords);
    }

    inline SkString invokeChildWithMatrix(int childIndex, EmitArgs& parentArgs) {
        return this->invokeChildWithMatrix(childIndex,
                                           /*inputColor=*/nullptr,
                                           /*destColor=*/nullptr,
                                           parentArgs);
    }

    // Invoke the child with the default destination color (solid white)
    inline SkString invokeChild(int childIndex,
                                const char* inputColor,
                                EmitArgs& parentArgs,
                                std::string_view skslCoords = {}) {
        return this->invokeChild(childIndex,
                                 inputColor,
                                 /*destColor=*/nullptr,
                                 parentArgs,
                                 skslCoords);
    }

    inline SkString invokeChildWithMatrix(int childIndex,
                                          const char* inputColor,
                                          EmitArgs& parentArgs) {
        return this->invokeChildWithMatrix(childIndex,
                                           inputColor,
                                           /*destColor=*/nullptr,
                                           parentArgs);
    }

    /** Invokes a child proc in its own scope. Pass in the parent's EmitArgs and invokeChild will
     *  automatically extract the coords and samplers of that child and pass them on to the child's
     *  emitCode(). Also, any uniforms or functions emitted by the child will have their names
     *  mangled to prevent redefinitions. The returned string contains the output color (as a call
     *  to the child's helper function). It is legal to pass nullptr as inputColor, since all
     *  fragment processors are required to work without an input color.
     *
     *  When skslCoords is empty, the child is invoked at the sample coordinates from parentArgs.
     *  When skslCoords is not empty, is must be an SkSL expression that evaluates to a float2.
     *  That expression is passed to the child's processor function as the "_coords" argument.
     */
    SkString invokeChild(int childIndex,
                         const char* inputColor,
                         const char* destColor,
                         EmitArgs& parentArgs,
                         std::string_view skslCoords = {});

    /**
     * As invokeChild, but transforms the coordinates according to the matrix expression attached
     * to the child's SampleUsage object. This is only valid if the child is sampled with a
     * const-uniform matrix.
     */
    SkString invokeChildWithMatrix(int childIndex,
                                   const char* inputColor,
                                   const char* destColor,
                                   EmitArgs& parentArgs);

    /**
     * Pre-order traversal of a GLSLFP hierarchy, or of multiple trees with roots in an array of
     * GLSLFPS. If initialized with an array color followed by coverage processors installed in a
     * program thenthe iteration order will agree with a GrFragmentProcessor::Iter initialized with
     * a GrPipeline that produces the same program key.
     */
    class Iter {
    public:
        Iter(std::unique_ptr<ProgramImpl> fps[], int cnt);
        Iter(ProgramImpl& fp) { fFPStack.push_back(&fp); }

        ProgramImpl& operator*() const;
        ProgramImpl* operator->() const;
        Iter& operator++();
        explicit operator bool() const { return !fFPStack.empty(); }

        // Because each iterator carries a stack we want to avoid copies.
        Iter(const Iter&) = delete;
        Iter& operator=(const Iter&) = delete;

    private:
        SkSTArray<4, ProgramImpl*, true> fFPStack;
    };

private:
    /**
     * A ProgramImpl instance can be reused with any GrFragmentProcessor that produces the same
     * the same key; this function reads data from a GrFragmentProcessor and uploads any
     * uniform variables required by the shaders created in emitCode(). The GrFragmentProcessor
     * parameter is guaranteed to be of the same type that created this ProgramImpl and
     * to have an identical key as the one that created this ProgramImpl.
     */
    virtual void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) {}

    // The (mangled) name of our entry-point function
    SkString fFunctionName;

    SkTArray<std::unique_ptr<ProgramImpl>, true> fChildProcessors;

    friend class GrFragmentProcessor;
};

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

SK_MAKE_BITFIELD_OPS(GrFragmentProcessor::OptimizationFlags)

static inline GrFPResult GrFPFailure(std::unique_ptr<GrFragmentProcessor> fp) {
    return {false, std::move(fp)};
}
static inline GrFPResult GrFPSuccess(std::unique_ptr<GrFragmentProcessor> fp) {
    SkASSERT(fp);
    return {true, std::move(fp)};
}

#endif
