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.
22  *
23  * There are two feedback loops between the GrFragmentProcessors, the GrXferProcessor, and the
24  * GrPrimitiveProcessor. These loops run on the CPU and to determine known properties of the final
25  * color and coverage inputs to the GrXferProcessor in order to perform optimizations that preserve
26  * correctness. The GrDrawOp seeds these loops with initial color and coverage, in its
27  * getFragmentProcessorAnalysisInputs implementation. These seed values are processed by the
28  * subsequent
29  * stages of the rendering pipeline and the output is then fed back into the GrDrawOp in
30  * the applyPipelineOptimizations call, where the op can use the information to inform decisions
31  * about GrPrimitiveProcessor creation.
32  */
33 
34 class GrGLSLPrimitiveProcessor;
35 
36 struct GrInitInvariantOutput;
37 
38 /*
39  * This class allows the GrPipeline to communicate information about the pipeline to a GrOp which
40  * inform its decisions for GrPrimitiveProcessor setup. These are not properly part of the pipeline
41  * because they reflect the specific inputs that the op provided to perform the analysis (e.g. that
42  * the GrGeometryProcessor would output an opaque color).
43  *
44  * The pipeline analysis that produced this may have decided to elide some GrProcessors. However,
45  * those elisions may depend upon changing the color output by the GrGeometryProcessor used by the
46  * GrDrawOp. The op must check getOverrideColorIfSet() for this.
47  */
48 class GrPipelineOptimizations {
49 public:
50     /** Does the pipeline require access to (implicit or explicit) local coordinates? */
readsLocalCoords()51     bool readsLocalCoords() const {
52         return SkToBool(kReadsLocalCoords_Flag & fFlags);
53     }
54 
55     /** Does the pipeline allow the GrPrimitiveProcessor to combine color and coverage into one
56         color output ? */
canTweakAlphaForCoverage()57     bool canTweakAlphaForCoverage() const {
58         return SkToBool(kCanTweakAlphaForCoverage_Flag & fFlags);
59     }
60 
61     /** Does the pipeline require the GrPrimitiveProcessor to specify a specific color (and if
62         so get the color)? */
getOverrideColorIfSet(GrColor * overrideColor)63     bool getOverrideColorIfSet(GrColor* overrideColor) const {
64         if (SkToBool(kUseOverrideColor_Flag & fFlags)) {
65             if (overrideColor) {
66                 *overrideColor = fOverrideColor;
67             }
68             return true;
69         }
70         return false;
71     }
72 
73 private:
74     enum {
75         // If this is not set the primitive processor need not produce local coordinates
76         kReadsLocalCoords_Flag = 0x1,
77 
78         // If this flag is set then the primitive processor may produce color*coverage as
79         // its color output (and not output a separate coverage).
80         kCanTweakAlphaForCoverage_Flag = 0x2,
81 
82         // If this flag is set the GrPrimitiveProcessor must produce fOverrideColor as its
83         // output color. If not set fOverrideColor is to be ignored.
84         kUseOverrideColor_Flag = 0x4,
85     };
86 
87     uint32_t    fFlags;
88     GrColor     fOverrideColor;
89 
90     friend class GrPipeline; // To initialize this
91 };
92 
93 /*
94  * GrPrimitiveProcessor defines an interface which all subclasses must implement.  All
95  * GrPrimitiveProcessors must proivide seed color and coverage for the Ganesh color / coverage
96  * pipelines, and they must provide some notion of equality
97  */
98 class GrPrimitiveProcessor : public GrProcessor {
99 public:
100     // Only the GrGeometryProcessor subclass actually has a geo shader or vertex attributes, but
101     // we put these calls on the base class to prevent having to cast
102     virtual bool willUseGeoShader() const = 0;
103 
104     struct Attribute {
AttributeAttribute105         Attribute()
106             : fName(nullptr)
107             , fType(kFloat_GrVertexAttribType)
108             , fOffset(0) {}
AttributeAttribute109         Attribute(const char* name, GrVertexAttribType type, GrSLPrecision precision)
110             : fName(name)
111             , fType(type)
112             , fOffset(SkAlign4(GrVertexAttribTypeSize(type)))
113             , fPrecision(precision) {}
114         const char* fName;
115         GrVertexAttribType fType;
116         size_t fOffset;
117         GrSLPrecision fPrecision;
118     };
119 
numAttribs()120     int numAttribs() const { return fAttribs.count(); }
getAttrib(int index)121     const Attribute& getAttrib(int index) const { return fAttribs[index]; }
122 
123     // Returns the vertex stride of the GP.  A common use case is to request geometry from a
124     // GrOpList based off of the stride, and to populate this memory using an implicit array of
125     // structs.  In this case, it is best to assert the vertexstride == sizeof(VertexStruct).
getVertexStride()126     size_t getVertexStride() const { return fVertexStride; }
127 
128     /**
129      * Computes a transformKey from an array of coord transforms. Will only look at the first
130      * <numCoords> transforms in the array.
131      *
132      * TODO: A better name for this function  would be "compute" instead of "get".
133      */
134     uint32_t getTransformKey(const SkTArray<const GrCoordTransform*, true>& coords,
135                              int numCoords) const;
136 
137     /**
138      * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this geometry
139      * processor's GL backend implementation.
140      *
141      * TODO: A better name for this function  would be "compute" instead of "get".
142      */
143     virtual void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;
144 
145 
146     /** Returns a new instance of the appropriate *GL* implementation class
147         for the given GrProcessor; caller is responsible for deleting
148         the object. */
149     virtual GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const = 0;
150 
isPathRendering()151     virtual bool isPathRendering() const { return false; }
152 
153     /**
154      * If non-null, overrides the dest color returned by GrGLSLFragmentShaderBuilder::dstColor().
155      */
getDestColorOverride()156     virtual const char* getDestColorOverride() const { return nullptr; }
157 
getSampleShading()158     virtual float getSampleShading() const {
159         return 0.0;
160     }
161 
162     /* Sub-class should override and return true if this primitive processor implements the distance
163      * vector field, a field of vectors to the nearest point in the edge of the shape.  */
implementsDistanceVector()164     virtual bool implementsDistanceVector() const { return false; }
165 
166 protected:
GrPrimitiveProcessor()167     GrPrimitiveProcessor() : fVertexStride(0) {}
168 
169     enum { kPreallocAttribCnt = 8 };
170     SkSTArray<kPreallocAttribCnt, Attribute> fAttribs;
171     size_t fVertexStride;
172 
173 private:
notifyRefCntIsZero()174     void notifyRefCntIsZero() const final {}
175     virtual bool hasExplicitLocalCoords() const = 0;
176 
177     typedef GrProcessor INHERITED;
178 };
179 
180 #endif
181