/*
 * 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 "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrProcessor.h"
#include "src/gpu/ops/GrOp.h"

class GrGLSLFragmentProcessor;
class GrPaint;
class GrPipeline;
class GrProcessorKeyBuilder;
class GrShaderCaps;
class GrSwizzle;

/** Provides custom fragment shader code. Fragment processors receive an input color (half4) and
    produce an output color. They may reference textures and uniforms. They may use
    GrCoordTransforms to receive a transformation of the local coordinates that map from local space
    to the fragment being processed.
 */
class GrFragmentProcessor : public GrProcessor {
public:
    class TextureSampler;

    /**
    *  In many instances (e.g. SkShader::asFragmentProcessor() implementations) it is desirable to
    *  only consider the input color's alpha. However, there is a competing desire to have reusable
    *  GrFragmentProcessor subclasses that can be used in other scenarios where the entire input
    *  color is considered. This function exists to filter the input color and pass it to a FP. It
    *  does so by returning a parent FP that multiplies the passed in FPs output by the parent's
    *  input alpha. The passed in FP will not receive an input color.
    */
    static std::unique_ptr<GrFragmentProcessor> MulChildByInputAlpha(
            std::unique_ptr<GrFragmentProcessor> child);

    /**
     *  Like MulChildByInputAlpha(), but reverses the sense of src and dst. In this case, return
     *  the input modulated by the child's alpha. The passed in FP will not receive an input color.
     *
     *  output = input * child.a
     */
    static std::unique_ptr<GrFragmentProcessor> MulInputByChildAlpha(
            std::unique_ptr<GrFragmentProcessor> child);

    /**
     *  This assumes that the input color to the returned processor will be unpremul and that the
     *  passed processor (which becomes the returned processor's child) produces a premul output.
     *  The result of the returned processor is a premul of its input color modulated by the child
     *  processor's premul output.
     */
    static std::unique_ptr<GrFragmentProcessor> MakeInputPremulAndMulByOutput(
            std::unique_ptr<GrFragmentProcessor>);

    /**
     *  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&,
                                                              bool useUniform = true);

    /**
     *  Returns a fragment processor that premuls the input before calling the passed in fragment
     *  processor.
     */
    static std::unique_ptr<GrFragmentProcessor> PremulInput(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 ensures
     *  the output is a valid premul color by clamping RGB to [0, A].
     */
    static std::unique_ptr<GrFragmentProcessor> ClampPremulOutput(
            std::unique_ptr<GrFragmentProcessor>);

    /**
     * Returns a fragment processor that runs the passed in array of fragment processors in a
     * series. The original input is passed to the first, the first's output is passed to the
     * second, etc. The output of the returned processor is the output of the last processor of the
     * series.
     *
     * The array elements with be moved.
     */
    static std::unique_ptr<GrFragmentProcessor> RunInSeries(std::unique_ptr<GrFragmentProcessor>*,
                                                            int cnt);

    /**
     * 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;

    GrGLSLFragmentProcessor* createGLSLInstance() const;

    void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
        this->onGetGLSLProcessorKey(caps, b);
        for (int i = 0; i < fChildProcessors.count(); ++i) {
            fChildProcessors[i]->getGLSLProcessorKey(caps, b);
        }
    }

    int numTextureSamplers() const { return fTextureSamplerCnt; }
    const TextureSampler& textureSampler(int i) const;

    int numCoordTransforms() const { return fCoordTransforms.count(); }

    /** Returns the coordinate transformation at index. index must be valid according to
        numCoordTransforms(). */
    const GrCoordTransform& coordTransform(int index) const { return *fCoordTransforms[index]; }
    GrCoordTransform& coordTransform(int index) { return *fCoordTransforms[index]; }

    const SkTArray<GrCoordTransform*, true>& coordTransforms() const {
        return fCoordTransforms;
    }

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

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

    SkDEBUGCODE(bool isInstantiated() const;)

    /** Do any of the coord transforms for this processor require local coords? */
    bool usesLocalCoords() const {
        // If the processor is sampled with explicit coords then we do not need to apply the
        // coord transforms in the vertex shader to the local coords.
        return SkToBool(fFlags & kHasCoordTranforms_Flag) &&
               SkToBool(fFlags & kCoordTransformsApplyToLocalCoords_Flag);
    }

    bool coordTransformsApplyToLocalCoords() const {
        return SkToBool(fFlags & kCoordTransformsApplyToLocalCoords_Flag);
    }

    void setSampledWithExplicitCoords(bool value) {
        if (value) {
            fFlags &= ~kCoordTransformsApplyToLocalCoords_Flag;
        } else {
            fFlags |= kCoordTransformsApplyToLocalCoords_Flag;
        }
        for (auto& child : fChildProcessors) {
            child->setSampledWithExplicitCoords(value);
        }
    }

    /**
     * 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 getGLSLProcessorKey
     */
    bool isEqual(const GrFragmentProcessor& that) const;

    void visitProxies(const GrOp::VisitProxyFunc& func);

    // A pre-order traversal iterator over a hierarchy of FPs. It can also iterate over all the FP
    // hierarchies rooted in a GrPaint, GrProcessorSet, or GrPipeline. For these collections it
    // iterates the tree rooted at each color FP and then each coverage FP.
    //
    // Iter is the non-const version and CIter is the const version.
    //
    // An iterator is constructed from one of the srcs and used like this:
    //   for (GrFragmentProcessor::Iter iter(pipeline); iter; ++iter) {
    //       GrFragmentProcessor& fp = *iter;
    //   }
    // The exit test for the loop is using Iter's operator bool().
    // To use a range-for loop instead see CIterRange below.
    class Iter;
    class CIter;

    // Used to implement a range-for loop using CIter. Src is one of GrFragmentProcessor,
    // GrPaint, GrProcessorSet, or GrPipeline. Type aliases for these defined below.
    // Example usage:
    //   for (const auto& fp : GrFragmentProcessor::PaintRange(paint)) {
    //       if (fp.usesLocalCoords()) {
    //       ...
    //       }
    //   }
    template <typename Src> class CIterRange;
    // Like CIterRange but non const and only constructable from GrFragmentProcessor. This could
    // support GrPaint as it owns non-const FPs but no need for it as of now.
    //   for (auto& fp0 : GrFragmentProcessor::IterRange(fp)) {
    //       ...
    //   }
    class IterRange;

    // We would use template deduction guides for Iter/CIter but for:
    // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79501
    // Instead we use these specialized type aliases to make it prettier
    // to construct Iters for particular sources of FPs.
    using FPCRange = CIterRange<GrFragmentProcessor>;
    using PaintCRange = CIterRange<GrPaint>;

    // Implementation details for iterators that walk an array of Items owned by a set of FPs.
    using CountFn = int (GrFragmentProcessor::*)() const;
    // Defined GetFn to be a member function that returns an Item by index. The function itself is
    // const if Item is a const type and non-const if Item is non-const.
    template <typename Item, bool IsConst = std::is_const<Item>::value> struct GetT;
    template <typename Item> struct GetT<Item, false> {
        using GetFn = Item& (GrFragmentProcessor::*)(int);
    };
    template <typename Item> struct GetT<Item, true> {
        using GetFn = const Item& (GrFragmentProcessor::*)(int) const;
    };
    template <typename Item> using GetFn = typename GetT<Item>::GetFn;
    // This is an iterator over the Items owned by a (collection of) FP. CountFn is a FP member that
    // gets the number of Items owned by each FP and GetFn is a member that gets them by index.
    template <typename Item, CountFn Count, GetFn<Item> Get> class FPItemIter;

    // Loops over all the GrCoordTransforms owned by GrFragmentProcessors. The possible sources for
    // the iteration are the same as those for Iter and the FPs are walked in the same order as
    // Iter. This provides access to the coord transform and the FP that owns it. Example usage:
    //   for (GrFragmentProcessor::CoordTransformIter iter(pipeline); iter; ++iter) {
    //       // transform is const GrCoordTransform& and owningFP is const GrFragmentProcessor&.
    //       auto [transform, owningFP] = *iter;
    //       ...
    //   }
    // See the ranges below to make this simpler a la range-for loops.
    using CoordTransformIter = FPItemIter<const GrCoordTransform,
                                          &GrFragmentProcessor::numCoordTransforms,
                                          &GrFragmentProcessor::coordTransform>;
    // Same as CoordTransformIter but for TextureSamplers:
    //   for (GrFragmentProcessor::TextureSamplerIter iter(pipeline); iter; ++iter) {
    //       // TextureSamplerIter is const GrFragmentProcessor::TextureSampler& and
    //       // owningFP is const GrFragmentProcessor&.
    //       auto [sampler, owningFP] = *iter;
    //       ...
    //   }
    // See the ranges below to make this simpler a la range-for loops.
    using TextureSamplerIter = FPItemIter<const TextureSampler,
                                          &GrFragmentProcessor::numTextureSamplers,
                                          &GrFragmentProcessor::textureSampler>;

    // Implementation detail for using CoordTransformIter and TextureSamplerIter in range-for loops.
    template <typename Src, typename ItemIter> class FPItemRange;

    // These allow iteration over coord transforms/texture samplers for various FP sources via
    // range-for loops. An example usage for looping over the coord transforms in a pipeline:
    // for (auto [transform, fp] : GrFragmentProcessor::PipelineCoordTransformRange(pipeline)) {
    //     ...
    // }
    // Only the combinations of FP sources and iterable things have been defined but it is easy
    // to add more as they become useful. Maybe someday we'll have template argument deduction
    // with guides for type aliases and the sources can be removed from the type aliases:
    // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1021r5.html
    using PipelineCoordTransformRange = FPItemRange<const GrPipeline, CoordTransformIter>;
    using PipelineTextureSamplerRange = FPItemRange<const GrPipeline, TextureSamplerIter>;
    using FPTextureSamplerRange = FPItemRange<const GrFragmentProcessor, TextureSamplerIter>;
    using ProcessorSetTextureSamplerRange = FPItemRange<const GrProcessorSet, TextureSamplerIter>;

    // Not used directly.
    using NonConstCoordTransformIter =
            FPItemIter<GrCoordTransform, &GrFragmentProcessor::numCoordTransforms,
                       &GrFragmentProcessor::coordTransform>;
    // Iterator over non-const GrCoordTransforms owned by FP and its descendants.
    using FPCoordTransformRange = FPItemRange<GrFragmentProcessor, NonConstCoordTransformIter>;

    // Sentinel type for range-for using Iter.
    class EndIter {};
    // Sentinel type for range-for using FPItemIter.
    class FPItemEndIter {};

protected:
    enum OptimizationFlags : uint32_t {
        kNone_OptimizationFlags,
        kCompatibleWithCoverageAsAlpha_OptimizationFlag = 0x1,
        kPreservesOpaqueInput_OptimizationFlag = 0x2,
        kConstantOutputForConstantInput_OptimizationFlag = 0x4,
        kAll_OptimizationFlags = kCompatibleWithCoverageAsAlpha_OptimizationFlag |
                                 kPreservesOpaqueInput_OptimizationFlag |
                                 kConstantOutputForConstantInput_OptimizationFlag
    };
    GR_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 | kCoordTransformsApplyToLocalCoords_Flag) {
        SkASSERT((optimizationFlags & ~kAll_OptimizationFlags) == 0);
    }

    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->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) {
        SkASSERT(fp.hasConstantOutputForConstantInput());
        return fp.constantOutputForConstantInput(input);
    }

    /**
     * Fragment Processor subclasses call this from their constructor to register coordinate
     * transformations. Coord transforms provide a mechanism for a processor to receive coordinates
     * in their FS code. The matrix expresses a transformation from local space. For a given
     * fragment the matrix will be applied to the local coordinate that maps to the fragment.
     *
     * When the transformation has perspective, the transformed coordinates will have
     * 3 components. Otherwise they'll have 2.
     *
     * This must only be called from the constructor because GrProcessors are immutable. The
     * processor subclass manages the lifetime of the transformations (this function only stores a
     * pointer). The GrCoordTransform is typically a member field of the GrProcessor subclass.
     *
     * A processor subclass that has multiple methods of construction should always add its coord
     * transforms in a consistent order. The non-virtual implementation of isEqual() automatically
     * compares transforms and will assume they line up across the two processor instances.
     */
    void addCoordTransform(GrCoordTransform*);

    /**
     * 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.
     */
    int registerChildProcessor(std::unique_ptr<GrFragmentProcessor> child);

    void setTextureSamplerCnt(int cnt) {
        SkASSERT(cnt >= 0);
        fTextureSamplerCnt = cnt;
    }

    /**
     * Helper for implementing onTextureSampler(). E.g.:
     * return IthTexureSampler(i, fMyFirstSampler, fMySecondSampler, fMyThirdSampler);
     */
    template <typename... Args>
    static const TextureSampler& IthTextureSampler(int i, const TextureSampler& samp0,
                                                   const Args&... samps) {
        return (0 == i) ? samp0 : IthTextureSampler(i - 1, samps...);
    }
    inline static const TextureSampler& IthTextureSampler(int i);

private:
    // Implementation details of Iter and CIter.
    template <typename> class IterBase;

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

    /** Returns a new instance of the appropriate *GL* implementation class
        for the given GrFragmentProcessor; caller is responsible for deleting
        the object. */
    virtual GrGLSLFragmentProcessor* onCreateGLSLInstance() const = 0;

    /** Implemented using GLFragmentProcessor::GenKey as described in this class's comment. */
    virtual void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) 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. they return the same object from
     * getFactory()). The processor subclass should not compare its coord transforms as that will
     * be performed automatically in the non-virtual isEqual().
     */
    virtual bool onIsEqual(const GrFragmentProcessor&) const = 0;

    virtual const TextureSampler& onTextureSampler(int) const { return IthTextureSampler(0); }

    bool hasSameTransforms(const GrFragmentProcessor&) const;

    enum PrivateFlags {
        kFirstPrivateFlag = kAll_OptimizationFlags + 1,
        kHasCoordTranforms_Flag = kFirstPrivateFlag,
        kCoordTransformsApplyToLocalCoords_Flag = kFirstPrivateFlag << 1,
    };

    uint32_t fFlags = kCoordTransformsApplyToLocalCoords_Flag;

    int fTextureSamplerCnt = 0;

    SkSTArray<4, GrCoordTransform*, true> fCoordTransforms;

    SkSTArray<1, std::unique_ptr<GrFragmentProcessor>, true> fChildProcessors;

    typedef GrProcessor INHERITED;
};

/**
 * Used to represent a texture that is required by a GrFragmentProcessor. It holds a GrTextureProxy
 * along with an associated GrSamplerState. TextureSamplers don't perform any coord manipulation to
 * account for texture origin.
 */
class GrFragmentProcessor::TextureSampler {
public:
    TextureSampler() = default;

    /**
     * This copy constructor is used by GrFragmentProcessor::clone() implementations.
     */
    explicit TextureSampler(const TextureSampler&) = default;

    TextureSampler(GrSurfaceProxyView, GrSamplerState = {});
    // TODO: Remove this ctor once all uses have been updated to pass in a GrSurfaceProxyView
    TextureSampler(sk_sp<GrSurfaceProxy>, GrSamplerState = {});

    TextureSampler& operator=(const TextureSampler&) = delete;

    bool operator==(const TextureSampler& that) const {
        return fView == that.fView && fSamplerState == that.fSamplerState;
    }

    bool operator!=(const TextureSampler& other) const { return !(*this == other); }

    SkDEBUGCODE(bool isInstantiated() const { return this->proxy()->isInstantiated(); })

    // 'peekTexture' should only ever be called after a successful 'instantiate' call
    GrTexture* peekTexture() const {
        SkASSERT(this->proxy()->isInstantiated());
        return this->proxy()->peekTexture();
    }

    const GrSurfaceProxyView& view() const { return fView; }
    GrSamplerState samplerState() const { return fSamplerState; }

    bool isInitialized() const { return SkToBool(this->proxy()); }

    GrSurfaceProxy* proxy() const { return fView.proxy(); }

#if GR_TEST_UTILS
    void set(GrSurfaceProxyView, GrSamplerState);
#endif

private:
    GrSurfaceProxyView    fView;
    GrSamplerState        fSamplerState;
};

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

const GrFragmentProcessor::TextureSampler& GrFragmentProcessor::IthTextureSampler(int i) {
    SK_ABORT("Illegal texture sampler index");
    static const TextureSampler kBogus;
    return kBogus;
}

GR_MAKE_BITFIELD_OPS(GrFragmentProcessor::OptimizationFlags)

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

template <typename FP> class GrFragmentProcessor::IterBase {
public:
    FP& operator*() const { return *fFPStack.back(); }
    FP* operator->() const { return fFPStack.back(); }
    operator bool() const { return !fFPStack.empty(); }
    bool operator!=(const EndIter&) { return (bool)*this; }

    // Hopefully this does not actually get called because of RVO.
    IterBase(const IterBase&) = default;

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

protected:
    void increment();

    IterBase() = default;
    explicit IterBase(FP& fp) { fFPStack.push_back(&fp); }

    SkSTArray<4, FP*, true> fFPStack;
};

template <typename FP> void GrFragmentProcessor::IterBase<FP>::increment() {
    SkASSERT(!fFPStack.empty());
    FP* back = fFPStack.back();
    fFPStack.pop_back();
    for (int i = back->numChildProcessors() - 1; i >= 0; --i) {
        fFPStack.push_back(&back->childProcessor(i));
    }
}

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

class GrFragmentProcessor::Iter : public IterBase<GrFragmentProcessor> {
public:
    explicit Iter(GrFragmentProcessor& fp) : IterBase(fp) {}
    Iter& operator++() {
        this->increment();
        return *this;
    }
};

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

class GrFragmentProcessor::CIter : public IterBase<const GrFragmentProcessor> {
public:
    explicit CIter(const GrFragmentProcessor& fp) : IterBase(fp) {}
    explicit CIter(const GrPaint&);
    explicit CIter(const GrProcessorSet&);
    explicit CIter(const GrPipeline&);
    CIter& operator++() {
        this->increment();
        return *this;
    }
};

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

template <typename Src> class GrFragmentProcessor::CIterRange {
public:
    explicit CIterRange(const Src& t) : fT(t) {}
    CIter begin() const { return CIter(fT); }
    EndIter end() const { return EndIter(); }

private:
    const Src& fT;
};

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

template <typename Item, GrFragmentProcessor::CountFn Count, GrFragmentProcessor::GetFn<Item> Get>
class GrFragmentProcessor::FPItemIter {
public:
    template <typename Src> explicit FPItemIter(Src& s);

    std::pair<Item&, const GrFragmentProcessor&> operator*() const {
        return {(*fFPIter.*Get)(fIndex), *fFPIter};
    }
    FPItemIter& operator++();
    operator bool() const { return fFPIter; }
    bool operator!=(const FPItemEndIter&) { return (bool)*this; }

    FPItemIter(const FPItemIter&) = delete;
    FPItemIter& operator=(const FPItemIter&) = delete;

private:
    typename std::conditional<std::is_const<Item>::value, CIter, Iter>::type fFPIter;
    int fIndex;
};

template <typename Item, GrFragmentProcessor::CountFn Count, GrFragmentProcessor::GetFn<Item> Get>
template <typename Src>
GrFragmentProcessor::FPItemIter<Item, Count, Get>::FPItemIter(Src& s) : fFPIter(s), fIndex(-1) {
    if (fFPIter) {
        ++*this;
    }
}

template <typename Item, GrFragmentProcessor::CountFn Count, GrFragmentProcessor::GetFn<Item> Get>
GrFragmentProcessor::FPItemIter<Item, Count, Get>&
GrFragmentProcessor::FPItemIter<Item, Count, Get>::operator++() {
    ++fIndex;
    if (fIndex < ((*fFPIter).*Count)()) {
        return *this;
    }
    fIndex = 0;
    do {} while (++fFPIter && !((*fFPIter).*Count)());
    return *this;
}

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

template <typename Src, typename ItemIter> class GrFragmentProcessor::FPItemRange {
public:
    FPItemRange(Src& src) : fSrc(src) {}
    ItemIter begin() const { return ItemIter(fSrc); }
    FPItemEndIter end() const { return FPItemEndIter(); }

private:
    Src& fSrc;
};

#endif
