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  * getProcessorAnalysisInputs 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 /*
37  * GrPrimitiveProcessor defines an interface which all subclasses must implement.  All
38  * GrPrimitiveProcessors must proivide seed color and coverage for the Ganesh color / coverage
39  * pipelines, and they must provide some notion of equality
40  */
41 class GrPrimitiveProcessor : public GrResourceIOProcessor, public GrProgramElement {
42 public:
43     struct Attribute {
44         enum class InputRate : bool {
45             kPerVertex,
46             kPerInstance
47         };
asShaderVarAttribute48         GrShaderVar asShaderVar() const {
49             return GrShaderVar(fName, GrVertexAttribTypeToSLType(fType),
50                                GrShaderVar::kIn_TypeModifier);
51         }
isInitializedAttribute52         bool isInitialized() const { return SkToBool(fName); }
53         Attribute() = default;
AttributeAttribute54         Attribute(const char* name, GrVertexAttribType type, int offset, InputRate rate)
55                 : fName(name), fType(type), fOffsetInRecord(offset), fInputRate(rate) {}
56         const char*          fName = nullptr;
57         GrVertexAttribType   fType;
58         int                  fOffsetInRecord;
59         InputRate            fInputRate;
60     };
61 
GrPrimitiveProcessor(ClassID classID)62     GrPrimitiveProcessor(ClassID classID)
63     : GrResourceIOProcessor(classID) {}
64 
numAttribs()65     int numAttribs() const { return fAttribs.count(); }
getAttrib(int index)66     const Attribute& getAttrib(int index) const { return fAttribs[index]; }
67 
hasVertexAttribs()68     bool hasVertexAttribs() const { return SkToBool(fVertexStride); }
hasInstanceAttribs()69     bool hasInstanceAttribs() const { return SkToBool(fInstanceStride); }
70 
71     /**
72      * These return the strides of the vertex and instance buffers. Attributes are expected to be
73      * laid out interleaved in their corresponding buffer (vertex or instance). fOffsetInRecord
74      * indicates an attribute's location in bytes relative to the first attribute. (These are padded
75      * to the nearest 4 bytes for performance reasons.)
76      *
77      * A common practice is to populate the buffer's memory using an implicit array of structs. In
78      * this case, it is best to assert:
79      *
80      *     stride == sizeof(struct) and
81      *     offsetof(struct, field[i]) == attrib[i].fOffsetInRecord
82      *
83      * NOTE: for instanced draws the vertex buffer has a single record that each instance reuses.
84      */
getVertexStride()85     int getVertexStride() const { return fVertexStride; }
getInstanceStride()86     int getInstanceStride() const { return fInstanceStride; }
87 
88     // Only the GrGeometryProcessor subclass actually has a geo shader or vertex attributes, but
89     // we put these calls on the base class to prevent having to cast
90     virtual bool willUseGeoShader() const = 0;
91 
willUsePrimitiveRestart()92     bool willUsePrimitiveRestart() const { return fWillUsePrimitiveRestart; }
93 
94     /**
95      * Computes a transformKey from an array of coord transforms. Will only look at the first
96      * <numCoords> transforms in the array.
97      *
98      * TODO: A better name for this function  would be "compute" instead of "get".
99      */
100     uint32_t getTransformKey(const SkTArray<const GrCoordTransform*, true>& coords,
101                              int numCoords) const;
102 
103     /**
104      * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this geometry
105      * processor's GL backend implementation.
106      *
107      * TODO: A better name for this function  would be "compute" instead of "get".
108      */
109     virtual void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;
110 
111 
112     /** Returns a new instance of the appropriate *GL* implementation class
113         for the given GrProcessor; caller is responsible for deleting
114         the object. */
115     virtual GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const = 0;
116 
isPathRendering()117     virtual bool isPathRendering() const { return false; }
118 
119     /**
120      * If non-null, overrides the dest color returned by GrGLSLFragmentShaderBuilder::dstColor().
121      */
getDestColorOverride()122     virtual const char* getDestColorOverride() const { return nullptr; }
123 
getSampleShading()124     virtual float getSampleShading() const {
125         return 0.0;
126     }
127 
128 protected:
129     /**
130      * Subclasses call these from their constructor to register vertex and instance attributes.
131      */
addVertexAttrib(const char * name,GrVertexAttribType type)132     const Attribute& addVertexAttrib(const char* name, GrVertexAttribType type) {
133         fAttribs.push_back() = {name, type, fVertexStride, Attribute::InputRate::kPerVertex};
134         fVertexStride += static_cast<int>(SkAlign4(GrVertexAttribTypeSize(type)));
135         return fAttribs.back();
136     }
addInstanceAttrib(const char * name,GrVertexAttribType type)137     const Attribute& addInstanceAttrib(const char* name, GrVertexAttribType type) {
138         fAttribs.push_back() = {name, type, fInstanceStride, Attribute::InputRate::kPerInstance};
139         fInstanceStride += static_cast<int>(SkAlign4(GrVertexAttribTypeSize(type)));
140         return fAttribs.back();
141     }
142 
setWillUsePrimitiveRestart()143     void setWillUsePrimitiveRestart() { fWillUsePrimitiveRestart = true; }
144 
145 private:
addPendingIOs()146     void addPendingIOs() const override { GrResourceIOProcessor::addPendingIOs(); }
removeRefs()147     void removeRefs() const override { GrResourceIOProcessor::removeRefs(); }
pendingIOComplete()148     void pendingIOComplete() const override { GrResourceIOProcessor::pendingIOComplete(); }
notifyRefCntIsZero()149     void notifyRefCntIsZero() const final {}
150     virtual bool hasExplicitLocalCoords() const = 0;
151 
152     SkSTArray<8, Attribute> fAttribs;
153     int fVertexStride = 0;
154     int fInstanceStride = 0;
155     bool fWillUsePrimitiveRestart = false;
156 
157     typedef GrProcessor INHERITED;
158 };
159 
160 #endif
161