16251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon/*
26251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon * Copyright 2014 Google Inc.
36251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon *
46251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon * Use of this source code is governed by a BSD-style license that can be
56251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon * found in the LICENSE file.
66251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon */
76251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
86251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon#ifndef GrFragmentProcessor_DEFINED
96251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon#define GrFragmentProcessor_DEFINED
106251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
116251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon#include "GrProcessor.h"
126251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
136251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomonclass GrCoordTransform;
14e9c0fc616d2a1632c285885b9b656b68ca8d4f24jvanverthclass GrGLSLCaps;
1564c4728c70001ed074fecf5c4e083781987b12e9egdanielclass GrGLSLFragmentProcessor;
16c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomonclass GrInvariantOutput;
17eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualittclass GrProcessorKeyBuilder;
186251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
196251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon/** Provides custom fragment shader code. Fragment processors receive an input color (vec4f) and
206251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    produce an output color. They may reference textures and uniforms. They may use
216251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    GrCoordTransforms to receive a transformation of the local coordinates that map from local space
226251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    to the fragment being processed.
236251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon */
246251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomonclass GrFragmentProcessor : public GrProcessor {
256251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomonpublic:
2687ba62e67c9ed0c453754a5341255829075c8e22bsalomon    /**
2787ba62e67c9ed0c453754a5341255829075c8e22bsalomon    *  In many instances (e.g. SkShader::asFragmentProcessor() implementations) it is desirable to
2887ba62e67c9ed0c453754a5341255829075c8e22bsalomon    *  only consider the input color's alpha. However, there is a competing desire to have reusable
2987ba62e67c9ed0c453754a5341255829075c8e22bsalomon    *  GrFragmentProcessor subclasses that can be used in other scenarios where the entire input
3087ba62e67c9ed0c453754a5341255829075c8e22bsalomon    *  color is considered. This function exists to filter the input color and pass it to a FP. It
3187ba62e67c9ed0c453754a5341255829075c8e22bsalomon    *  does so by returning a parent FP that multiplies the passed in FPs output by the parent's
3287ba62e67c9ed0c453754a5341255829075c8e22bsalomon    *  input alpha. The passed in FP will not receive an input color.
3387ba62e67c9ed0c453754a5341255829075c8e22bsalomon    */
34f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon    static const GrFragmentProcessor* MulOutputByInputAlpha(const GrFragmentProcessor*);
35f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon
36f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon    /**
37f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon     *  Similar to the above but it modulates the output r,g,b of the child processor by the input
38f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon     *  rgb and then multiplies all the components by the input alpha. This effectively modulates
39f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon     *  the child processor's premul color by a unpremul'ed input and produces a premul output
40f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon     */
41f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon    static const GrFragmentProcessor* MulOutputByInputUnpremulColor(const GrFragmentProcessor*);
42f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon
43f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon    /**
44e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon     *  Returns a parent fragment processor that adopts the passed fragment processor as a child.
45e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon     *  The parent will ignore its input color and instead feed the passed in color as input to the
46e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon     *  child.
47f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon     */
48f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon    static const GrFragmentProcessor* OverrideInput(const GrFragmentProcessor*, GrColor);
4987ba62e67c9ed0c453754a5341255829075c8e22bsalomon
50e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon    /**
51e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon     * Returns a fragment processor that runs the passed in array of fragment processors in a
52e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon     * series. The original input is passed to the first, the first's output is passed to the
53e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon     * second, etc. The output of the returned processor is the output of the last processor of the
54e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon     * series.
55e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon     */
56e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon    static const GrFragmentProcessor* RunInSeries(const GrFragmentProcessor*[], int cnt);
57e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon
586251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    GrFragmentProcessor()
596251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon        : INHERITED()
6093ab254b7e4ce82074e88e219a8e32b31086ca86wangyix        , fUsesLocalCoords(false)
6193ab254b7e4ce82074e88e219a8e32b31086ca86wangyix        , fNumTexturesExclChildren(0)
6293ab254b7e4ce82074e88e219a8e32b31086ca86wangyix        , fNumTransformsExclChildren(0) {}
636251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
64ac856c97acc84dcb54d9cdb068ec8a02b8869647bsalomon    ~GrFragmentProcessor() override;
65ac856c97acc84dcb54d9cdb068ec8a02b8869647bsalomon
6657d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel    GrGLSLFragmentProcessor* createGLSLInstance() const;
67eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
6857d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel    void getGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const {
6957d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel        this->onGetGLSLProcessorKey(caps, b);
704b3050b410254d0cb38df9a30ae2e209124fa1a2wangyix        for (int i = 0; i < fChildProcessors.count(); ++i) {
7157d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel            fChildProcessors[i]->getGLSLProcessorKey(caps, b);
724b3050b410254d0cb38df9a30ae2e209124fa1a2wangyix        }
734b3050b410254d0cb38df9a30ae2e209124fa1a2wangyix    }
744b3050b410254d0cb38df9a30ae2e209124fa1a2wangyix
7593ab254b7e4ce82074e88e219a8e32b31086ca86wangyix    int numTexturesExclChildren() const { return fNumTexturesExclChildren; }
7693ab254b7e4ce82074e88e219a8e32b31086ca86wangyix
7793ab254b7e4ce82074e88e219a8e32b31086ca86wangyix    int numTransformsExclChildren() const { return fNumTransformsExclChildren; }
7893ab254b7e4ce82074e88e219a8e32b31086ca86wangyix
796251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    int numTransforms() const { return fCoordTransforms.count(); }
806251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
816251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    /** Returns the coordinate transformation at index. index must be valid according to
826251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon        numTransforms(). */
836251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    const GrCoordTransform& coordTransform(int index) const { return *fCoordTransforms[index]; }
846251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
85abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt    const SkTArray<const GrCoordTransform*, true>& coordTransforms() const {
86abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt        return fCoordTransforms;
87abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt    }
88abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt
892fe7923f7e74f901a17afba7609d71a1220bdc60joshualitt    void gatherCoordTransforms(SkTArray<const GrCoordTransform*, true>* outTransforms) const {
9058d890bd45a201477ec6c4ba0ae61c574b4e5aefwangyix        if (!fCoordTransforms.empty()) {
9158d890bd45a201477ec6c4ba0ae61c574b4e5aefwangyix            outTransforms->push_back_n(fCoordTransforms.count(), fCoordTransforms.begin());
922fe7923f7e74f901a17afba7609d71a1220bdc60joshualitt        }
932fe7923f7e74f901a17afba7609d71a1220bdc60joshualitt    }
942fe7923f7e74f901a17afba7609d71a1220bdc60joshualitt
954b3050b410254d0cb38df9a30ae2e209124fa1a2wangyix    int numChildProcessors() const { return fChildProcessors.count(); }
964b3050b410254d0cb38df9a30ae2e209124fa1a2wangyix
97ac856c97acc84dcb54d9cdb068ec8a02b8869647bsalomon    const GrFragmentProcessor& childProcessor(int index) const { return *fChildProcessors[index]; }
984b3050b410254d0cb38df9a30ae2e209124fa1a2wangyix
99290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt    /** Do any of the coordtransforms for this processor require local coords? */
100290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt    bool usesLocalCoords() const { return fUsesLocalCoords; }
101290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt
102eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    /** Returns true if this and other processor conservatively draw identically. It can only return
103eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt        true when the two processor are of the same subclass (i.e. they return the same object from
1046251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon        from getFactory()).
1056251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
106eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt        A return value of true from isEqual() should not be used to test whether the processor would
10757d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel        generate the same shader code. To test for identical code generation use getGLSLProcessorKey
10857d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel     */
10954017d7e5b09e7ca58346ea72ff065677fcd7be1wangyix    bool isEqual(const GrFragmentProcessor& that, bool ignoreCoordTransforms) const;
1106251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
11156995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt    /**
11256995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt     * This function is used to perform optimizations. When called the invarientOuput param
11356995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt     * indicate whether the input components to this processor in the FS will have known values.
11456995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt     * In inout the validFlags member is a bitfield of GrColorComponentFlags. The isSingleComponent
11556995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt     * member indicates whether the input will be 1 or 4 bytes. The function updates the members of
11656995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt     * inout to indicate known values of its output. A component of the color member only has
11756995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt     * meaning if the corresponding bit in validFlags is set.
11856995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt     */
119c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon    void computeInvariantOutput(GrInvariantOutput* inout) const {
120c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon        this->onComputeInvariantOutput(inout);
121c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon    }
12256995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt
1236251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomonprotected:
12493ab254b7e4ce82074e88e219a8e32b31086ca86wangyix    void addTextureAccess(const GrTextureAccess* textureAccess) override;
12593ab254b7e4ce82074e88e219a8e32b31086ca86wangyix
1266251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    /**
1276251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon     * Fragment Processor subclasses call this from their constructor to register coordinate
128de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * transformations. Coord transforms provide a mechanism for a processor to receive coordinates
129de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * in their FS code. The matrix expresses a transformation from local space. For a given
130de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * fragment the matrix will be applied to the local coordinate that maps to the fragment.
131de258cd6b402c4da78b66e88191ad02162d87916bsalomon     *
132de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * When the transformation has perspective, the transformed coordinates will have
133790d74f7c1db73e2938eee6a6eb78bc29be7b851mtklein     * 3 components. Otherwise they'll have 2.
134de258cd6b402c4da78b66e88191ad02162d87916bsalomon     *
135de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * This must only be called from the constructor because GrProcessors are immutable. The
136de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * processor subclass manages the lifetime of the transformations (this function only stores a
137790d74f7c1db73e2938eee6a6eb78bc29be7b851mtklein     * pointer). The GrCoordTransform is typically a member field of the GrProcessor subclass.
138de258cd6b402c4da78b66e88191ad02162d87916bsalomon     *
139de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * A processor subclass that has multiple methods of construction should always add its coord
140de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * transforms in a consistent order. The non-virtual implementation of isEqual() automatically
141de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * compares transforms and will assume they line up across the two processor instances.
1426251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon     */
1436251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    void addCoordTransform(const GrCoordTransform*);
1446251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
1456251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    /**
14658d890bd45a201477ec6c4ba0ae61c574b4e5aefwangyix     * FragmentProcessor subclasses call this from their constructor to register any child
14793ab254b7e4ce82074e88e219a8e32b31086ca86wangyix     * FragmentProcessors they have. This must be called AFTER all texture accesses and coord
14893ab254b7e4ce82074e88e219a8e32b31086ca86wangyix     * transforms have been added.
1494b3050b410254d0cb38df9a30ae2e209124fa1a2wangyix     * This is for processors whose shader code will be composed of nested processors whose output
1504b3050b410254d0cb38df9a30ae2e209124fa1a2wangyix     * colors will be combined somehow to produce its output color.  Registering these child
15158d890bd45a201477ec6c4ba0ae61c574b4e5aefwangyix     * processors will allow the ProgramBuilder to automatically handle their transformed coords and
15258d890bd45a201477ec6c4ba0ae61c574b4e5aefwangyix     * texture accesses and mangle their uniform and output color names.
1534b3050b410254d0cb38df9a30ae2e209124fa1a2wangyix     */
15458d890bd45a201477ec6c4ba0ae61c574b4e5aefwangyix    int registerChildProcessor(const GrFragmentProcessor* child);
1554b3050b410254d0cb38df9a30ae2e209124fa1a2wangyix
1564b3050b410254d0cb38df9a30ae2e209124fa1a2wangyix    /**
15756995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt     * Subclass implements this to support getConstantColorComponents(...).
15854017d7e5b09e7ca58346ea72ff065677fcd7be1wangyix     *
15954017d7e5b09e7ca58346ea72ff065677fcd7be1wangyix     * Note: it's up to the subclass implementation to do any recursive call to compute the child
16054017d7e5b09e7ca58346ea72ff065677fcd7be1wangyix     * procs' output invariants; computeInvariantOutput will not be recursive.
16156995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt     */
16256995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt    virtual void onComputeInvariantOutput(GrInvariantOutput* inout) const = 0;
16356995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt
1646251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomonprivate:
1654204800cd8f311f11491cf2eb7e32ca681f05489bsalomon    void notifyRefCntIsZero() const final;
1664204800cd8f311f11491cf2eb7e32ca681f05489bsalomon
167b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyix    /** Returns a new instance of the appropriate *GL* implementation class
168b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyix        for the given GrFragmentProcessor; caller is responsible for deleting
169b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyix        the object. */
17057d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel    virtual GrGLSLFragmentProcessor* onCreateGLSLInstance() const = 0;
171b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyix
1724b3050b410254d0cb38df9a30ae2e209124fa1a2wangyix    /** Implemented using GLFragmentProcessor::GenKey as described in this class's comment. */
17357d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel    virtual void onGetGLSLProcessorKey(const GrGLSLCaps& caps,
17457d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel                                       GrProcessorKeyBuilder* b) const = 0;
1754b3050b410254d0cb38df9a30ae2e209124fa1a2wangyix
176de258cd6b402c4da78b66e88191ad02162d87916bsalomon    /**
177de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * Subclass implements this to support isEqual(). It will only be called if it is known that
178de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * the two processors are of the same subclass (i.e. they return the same object from
179de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * getFactory()). The processor subclass should not compare its coord transforms as that will
180de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * be performed automatically in the non-virtual isEqual().
181de258cd6b402c4da78b66e88191ad02162d87916bsalomon     */
182de258cd6b402c4da78b66e88191ad02162d87916bsalomon    virtual bool onIsEqual(const GrFragmentProcessor&) const = 0;
183de258cd6b402c4da78b66e88191ad02162d87916bsalomon
184de258cd6b402c4da78b66e88191ad02162d87916bsalomon    bool hasSameTransforms(const GrFragmentProcessor&) const;
1856251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
186418e26f86c7a9dd2096cfc5501f86c559c7689d7bsalomon    bool                                            fUsesLocalCoords;
18758d890bd45a201477ec6c4ba0ae61c574b4e5aefwangyix
18858d890bd45a201477ec6c4ba0ae61c574b4e5aefwangyix    /**
18969ed114d388c56e83a2385d8b8182e6d05a0b073wangyix     * fCoordTransforms stores the transforms of this proc, followed by all the transforms of this
19069ed114d388c56e83a2385d8b8182e6d05a0b073wangyix     * proc's children. In other words, each proc stores all the transforms of its subtree as if
19169ed114d388c56e83a2385d8b8182e6d05a0b073wangyix     * they were collected using preorder traversal.
19269ed114d388c56e83a2385d8b8182e6d05a0b073wangyix     *
19369ed114d388c56e83a2385d8b8182e6d05a0b073wangyix     * Example:
19469ed114d388c56e83a2385d8b8182e6d05a0b073wangyix     * Suppose we have frag proc A, who has two children B and D. B has a child C, and D has
19569ed114d388c56e83a2385d8b8182e6d05a0b073wangyix     * two children E and F. Suppose procs A, B, C, D, E, F have 1, 2, 1, 1, 3, 2 transforms
19669ed114d388c56e83a2385d8b8182e6d05a0b073wangyix     * respectively. The following shows what the fCoordTransforms array of each proc would contain:
19769ed114d388c56e83a2385d8b8182e6d05a0b073wangyix     *
19869ed114d388c56e83a2385d8b8182e6d05a0b073wangyix     *                                   (A)
19969ed114d388c56e83a2385d8b8182e6d05a0b073wangyix     *                        [a1,b1,b2,c1,d1,e1,e2,e3,f1,f2]
20069ed114d388c56e83a2385d8b8182e6d05a0b073wangyix     *                                  /    \
20169ed114d388c56e83a2385d8b8182e6d05a0b073wangyix     *                                /        \
20269ed114d388c56e83a2385d8b8182e6d05a0b073wangyix     *                            (B)           (D)
20369ed114d388c56e83a2385d8b8182e6d05a0b073wangyix     *                        [b1,b2,c1]   [d1,e1,e2,e3,f1,f2]
20469ed114d388c56e83a2385d8b8182e6d05a0b073wangyix     *                          /             /    \
20569ed114d388c56e83a2385d8b8182e6d05a0b073wangyix     *                        /             /        \
20669ed114d388c56e83a2385d8b8182e6d05a0b073wangyix     *                      (C)          (E)          (F)
20769ed114d388c56e83a2385d8b8182e6d05a0b073wangyix     *                     [c1]      [e1,e2,e3]      [f1,f2]
20869ed114d388c56e83a2385d8b8182e6d05a0b073wangyix     *
20958d890bd45a201477ec6c4ba0ae61c574b4e5aefwangyix     * The same goes for fTextureAccesses with textures.
21058d890bd45a201477ec6c4ba0ae61c574b4e5aefwangyix     */
211418e26f86c7a9dd2096cfc5501f86c559c7689d7bsalomon    SkSTArray<4, const GrCoordTransform*, true>     fCoordTransforms;
212418e26f86c7a9dd2096cfc5501f86c559c7689d7bsalomon    int                                             fNumTexturesExclChildren;
213418e26f86c7a9dd2096cfc5501f86c559c7689d7bsalomon    int                                             fNumTransformsExclChildren;
214e416d940c64d7e9b3ef8eb62a2a4ce8e5794e13eBrian Salomon    SkSTArray<1, const GrFragmentProcessor*, true>  fChildProcessors;
2156251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
2166251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    typedef GrProcessor INHERITED;
2176251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon};
2186251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
2196251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon#endif
220