/*
 * 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/GrProcessor.h"
#include "src/gpu/glsl/GrGLSLUniformHandler.h"

#include <tuple>

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

namespace skgpu {
class KeyBuilder;
}

/**
 * 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 GrSwizzle&);

    /**
     *  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,
                                SkSL::String 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,
                                SkSL::String 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,
                         SkSL::String 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++();
        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
