• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2013 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef GrPrimitiveProcessor_DEFINED
9 #define GrPrimitiveProcessor_DEFINED
10 
11 #include "GrColor.h"
12 #include "GrProcessor.h"
13 #include "GrShaderVar.h"
14 
15 /*
16  * The GrPrimitiveProcessor represents some kind of geometric primitive.  This includes the shape
17  * of the primitive and the inherent color of the primitive.  The GrPrimitiveProcessor is
18  * responsible for providing a color and coverage input into the Ganesh rendering pipeline.  Through
19  * optimization, Ganesh may decide a different color, no color, and / or no coverage are required
20  * from the GrPrimitiveProcessor, so the GrPrimitiveProcessor must be able to support this
21  * functionality.  We also use the GrPrimitiveProcessor to make batching decisions.
22  *
23  * There are two feedback loops between the GrFragmentProcessors, the GrXferProcessor, and the
24  * GrPrimitiveProcessor.  These loops run on the CPU and compute any invariant components which
25  * might be useful for correctness / optimization decisions.  The GrPrimitiveProcessor seeds these
26  * loops, one with initial color and one with initial coverage, in its
27  * onComputeInvariantColor / Coverage calls.  These seed values are processed by the subsequent
28  * stages of the rendering pipeline and the output is then fed back into the GrPrimitiveProcessor in
29  * the initBatchTracker call, where the GrPrimitiveProcessor can then initialize the GrBatchTracker
30  * struct with the appropriate values.
31  *
32  * We are evolving this system to move towards generating geometric meshes and their associated
33  * vertex data after we have batched and reordered draws.  This system, known as 'deferred geometry'
34  * will allow the GrPrimitiveProcessor much greater control over how data is transmitted to shaders.
35  *
36  * In a deferred geometry world, the GrPrimitiveProcessor can always 'batch'  To do this, each
37  * primitive type is associated with one GrPrimitiveProcessor, who has complete control of how
38  * it draws.  Each primitive draw will bundle all required data to perform the draw, and these
39  * bundles of data will be owned by an instance of the associated GrPrimitiveProcessor.  Bundles
40  * can be updated alongside the GrBatchTracker struct itself, ultimately allowing the
41  * GrPrimitiveProcessor complete control of how it gets data into the fragment shader as long as
42  * it emits the appropriate color, or none at all, as directed.
43  */
44 
45 class GrGLSLCaps;
46 class GrGLSLPrimitiveProcessor;
47 
48 struct GrInitInvariantOutput;
49 
50 // Describes the state of pixel local storage with respect to the current draw.
51 enum GrPixelLocalStorageState {
52     // The draw is actively updating PLS.
53     kDraw_GrPixelLocalStorageState,
54     // The draw is a "finish" operation which is reading from PLS and writing color.
55     kFinish_GrPixelLocalStorageState,
56     // The draw does not use PLS.
57     kDisabled_GrPixelLocalStorageState
58 };
59 
60 /*
61  * This class allows the GrPipeline to communicate information about the pipeline to a
62  * GrBatch which should be forwarded to the GrPrimitiveProcessor(s) created by the batch.
63  * These are not properly part of the pipeline because they assume the specific inputs
64  * that the batch provided when it created the pipeline. Identical pipelines may be
65  * created by different batches with different input assumptions and therefore different
66  * computed optimizations. It is the batch-specific optimizations that allow the pipelines
67  * to be equal.
68  */
69 class GrXPOverridesForBatch {
70 public:
71     /** Does the pipeline require the GrPrimitiveProcessor's color? */
readsColor()72     bool readsColor() const { return SkToBool(kReadsColor_Flag & fFlags); }
73 
74     /** Does the pipeline require the GrPrimitiveProcessor's coverage? */
readsCoverage()75     bool readsCoverage() const { return
76         SkToBool(kReadsCoverage_Flag & fFlags); }
77 
78     /** Does the pipeline require access to (implicit or explicit) local coordinates? */
readsLocalCoords()79     bool readsLocalCoords() const {
80         return SkToBool(kReadsLocalCoords_Flag & fFlags);
81     }
82 
83     /** Does the pipeline allow the GrPrimitiveProcessor to combine color and coverage into one
84         color output ? */
canTweakAlphaForCoverage()85     bool canTweakAlphaForCoverage() const {
86         return SkToBool(kCanTweakAlphaForCoverage_Flag & fFlags);
87     }
88 
89     /** Does the pipeline require the GrPrimitiveProcessor to specify a specific color (and if
90         so get the color)? */
getOverrideColorIfSet(GrColor * overrideColor)91     bool getOverrideColorIfSet(GrColor* overrideColor) const {
92         if (SkToBool(kUseOverrideColor_Flag & fFlags)) {
93             SkASSERT(SkToBool(kReadsColor_Flag & fFlags));
94             if (overrideColor) {
95                 *overrideColor = fOverrideColor;
96             }
97             return true;
98         }
99         return false;
100     }
101 
102     /**
103      * Returns true if the pipeline's color output will be affected by the existing render target
104      * destination pixel values (meaning we need to be careful with overlapping draws). Note that we
105      * can conflate coverage and color, so the destination color may still bleed into pixels that
106      * have partial coverage, even if this function returns false.
107      *
108      * The above comment seems incorrect for the use case. This funciton is used to turn two
109      * overlapping draws into a single draw (really to stencil multiple paths and do a single
110      * cover). It seems that what really matters is whether the dst is read for color OR for
111      * coverage.
112      */
willColorBlendWithDst()113     bool willColorBlendWithDst() const { return SkToBool(kWillColorBlendWithDst_Flag & fFlags); }
114 
115 private:
116     enum {
117         // If this is not set the primitive processor need not produce a color output
118         kReadsColor_Flag                = 0x1,
119 
120         // If this is not set the primitive processor need not produce a coverage output
121         kReadsCoverage_Flag             = 0x2,
122 
123         // If this is not set the primitive processor need not produce local coordinates
124         kReadsLocalCoords_Flag          = 0x4,
125 
126         // If this flag is set then the primitive processor may produce color*coverage as
127         // its color output (and not output a separate coverage).
128         kCanTweakAlphaForCoverage_Flag  = 0x8,
129 
130         // If this flag is set the GrPrimitiveProcessor must produce fOverrideColor as its
131         // output color. If not set fOverrideColor is to be ignored.
132         kUseOverrideColor_Flag          = 0x10,
133 
134         kWillColorBlendWithDst_Flag     = 0x20,
135     };
136 
137     uint32_t    fFlags;
138     GrColor     fOverrideColor;
139 
140     friend class GrPipeline; // To initialize this
141 };
142 
143 /*
144  * GrPrimitiveProcessor defines an interface which all subclasses must implement.  All
145  * GrPrimitiveProcessors must proivide seed color and coverage for the Ganesh color / coverage
146  * pipelines, and they must provide some notion of equality
147  */
148 class GrPrimitiveProcessor : public GrProcessor {
149 public:
150     // Only the GrGeometryProcessor subclass actually has a geo shader or vertex attributes, but
151     // we put these calls on the base class to prevent having to cast
152     virtual bool willUseGeoShader() const = 0;
153 
154     /*
155      * This is a safeguard to prevent GrPrimitiveProcessor's from going beyond platform specific
156      * attribute limits. This number can almost certainly be raised if required.
157      */
158     static const int kMaxVertexAttribs = 8;
159 
160     struct Attribute {
AttributeAttribute161         Attribute()
162             : fName(nullptr)
163             , fType(kFloat_GrVertexAttribType)
164             , fOffset(0) {}
165         Attribute(const char* name, GrVertexAttribType type,
166                   GrSLPrecision precision = kDefault_GrSLPrecision)
fNameAttribute167             : fName(name)
168             , fType(type)
169             , fOffset(SkAlign4(GrVertexAttribTypeSize(type)))
170             , fPrecision(precision) {}
171         const char* fName;
172         GrVertexAttribType fType;
173         size_t fOffset;
174         GrSLPrecision fPrecision;
175     };
176 
numAttribs()177     int numAttribs() const { return fNumAttribs; }
getAttrib(int index)178     const Attribute& getAttrib(int index) const {
179         SkASSERT(index < fNumAttribs);
180         return fAttribs[index];
181     }
182 
183     // Returns the vertex stride of the GP.  A common use case is to request geometry from a
184     // drawtarget based off of the stride, and to populate this memory using an implicit array of
185     // structs.  In this case, it is best to assert the vertexstride == sizeof(VertexStruct).
getVertexStride()186     size_t getVertexStride() const { return fVertexStride; }
187 
188     /**
189      * Computes a transformKey from an array of coord transforms. Will only look at the first
190      * <numCoords> transforms in the array.
191      *
192      * TODO: A better name for this function  would be "compute" instead of "get".
193      */
194     uint32_t getTransformKey(const SkTArray<const GrCoordTransform*, true>& coords,
195                              int numCoords) const;
196 
197     /**
198      * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this geometry
199      * processor's GL backend implementation.
200      *
201      * TODO: A better name for this function  would be "compute" instead of "get".
202      */
203     virtual void getGLSLProcessorKey(const GrGLSLCaps& caps,
204                                      GrProcessorKeyBuilder* b) const = 0;
205 
206 
207     /** Returns a new instance of the appropriate *GL* implementation class
208         for the given GrProcessor; caller is responsible for deleting
209         the object. */
210     virtual GrGLSLPrimitiveProcessor* createGLSLInstance(const GrGLSLCaps& caps) const = 0;
211 
isPathRendering()212     virtual bool isPathRendering() const { return false; }
213 
214     /**
215      * No Local Coord Transformation is needed in the shader, instead transformed local coords will
216      * be provided via vertex attribute.
217      */
218     virtual bool hasTransformedLocalCoords() const = 0;
219 
getPixelLocalStorageState()220     virtual GrPixelLocalStorageState getPixelLocalStorageState() const {
221         return kDisabled_GrPixelLocalStorageState;
222     }
223 
224     /**
225      * If non-null, overrides the dest color returned by GrGLSLFragmentShaderBuilder::dstColor().
226      */
getDestColorOverride()227     virtual const char* getDestColorOverride() const { return nullptr; }
228 
229 protected:
GrPrimitiveProcessor()230     GrPrimitiveProcessor()
231         : fNumAttribs(0)
232         , fVertexStride(0) {}
233 
234     Attribute fAttribs[kMaxVertexAttribs];
235     int fNumAttribs;
236     size_t fVertexStride;
237 
238 private:
notifyRefCntIsZero()239     void notifyRefCntIsZero() const final {};
240     virtual bool hasExplicitLocalCoords() const = 0;
241 
242     typedef GrProcessor INHERITED;
243 };
244 
245 #endif
246