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 "GrNonAtomicRef.h"
13 #include "GrProcessor.h"
14 #include "GrProxyRef.h"
15 #include "GrShaderVar.h"
16 
17 class GrCoordTransform;
18 
19 /*
20  * The GrPrimitiveProcessor represents some kind of geometric primitive.  This includes the shape
21  * of the primitive and the inherent color of the primitive.  The GrPrimitiveProcessor is
22  * responsible for providing a color and coverage input into the Ganesh rendering pipeline.  Through
23  * optimization, Ganesh may decide a different color, no color, and / or no coverage are required
24  * from the GrPrimitiveProcessor, so the GrPrimitiveProcessor must be able to support this
25  * functionality.
26  *
27  * There are two feedback loops between the GrFragmentProcessors, the GrXferProcessor, and the
28  * GrPrimitiveProcessor. These loops run on the CPU and to determine known properties of the final
29  * color and coverage inputs to the GrXferProcessor in order to perform optimizations that preserve
30  * correctness. The GrDrawOp seeds these loops with initial color and coverage, in its
31  * getProcessorAnalysisInputs implementation. These seed values are processed by the
32  * subsequent
33  * stages of the rendering pipeline and the output is then fed back into the GrDrawOp in
34  * the applyPipelineOptimizations call, where the op can use the information to inform decisions
35  * about GrPrimitiveProcessor creation.
36  */
37 
38 class GrGLSLPrimitiveProcessor;
39 
40 /**
41  * GrPrimitiveProcessor defines an interface which all subclasses must implement.  All
42  * GrPrimitiveProcessors must proivide seed color and coverage for the Ganesh color / coverage
43  * pipelines, and they must provide some notion of equality
44  *
45  * TODO: This class does not really need to be ref counted. Instances should be allocated using
46  * GrOpFlushState's arena and destroyed when the arena is torn down.
47  */
48 class GrPrimitiveProcessor : public GrProcessor, public GrNonAtomicRef<GrPrimitiveProcessor> {
49 public:
50     class TextureSampler;
51 
52     /** Describes a vertex or instance attribute. */
53     class Attribute {
54     public:
55         constexpr Attribute() = default;
Attribute(const char * name,GrVertexAttribType cpuType,GrSLType gpuType)56         constexpr Attribute(const char* name,
57                             GrVertexAttribType cpuType,
58                             GrSLType gpuType)
59             : fName(name), fCPUType(cpuType), fGPUType(gpuType) {}
60         constexpr Attribute(const Attribute&) = default;
61 
62         Attribute& operator=(const Attribute&) = default;
63 
isInitialized()64         constexpr bool isInitialized() const { return SkToBool(fName); }
65 
name()66         constexpr const char* name() const { return fName; }
cpuType()67         constexpr GrVertexAttribType cpuType() const { return fCPUType; }
gpuType()68         constexpr GrSLType           gpuType() const { return fGPUType; }
69 
70         inline constexpr size_t size() const;
sizeAlign4()71         constexpr size_t sizeAlign4() const { return SkAlign4(this->size()); }
72 
asShaderVar()73         GrShaderVar asShaderVar() const {
74             return {fName, fGPUType, GrShaderVar::kIn_TypeModifier};
75         }
76 
77     private:
78         const char* fName = nullptr;
79         GrVertexAttribType fCPUType = kFloat_GrVertexAttribType;
80         GrSLType fGPUType = kFloat_GrSLType;
81     };
82 
83     class Iter {
84     public:
Iter()85         Iter() : fCurr(nullptr), fRemaining(0) {}
Iter(const Iter & iter)86         Iter(const Iter& iter) : fCurr(iter.fCurr), fRemaining(iter.fRemaining) {}
87         Iter& operator= (const Iter& iter) {
88             fCurr = iter.fCurr;
89             fRemaining = iter.fRemaining;
90             return *this;
91         }
Iter(const Attribute * attrs,int count)92         Iter(const Attribute* attrs, int count) : fCurr(attrs), fRemaining(count) {
93             this->skipUninitialized();
94         }
95 
96         bool operator!=(const Iter& that) const { return fCurr != that.fCurr; }
97         const Attribute& operator*() const { return *fCurr; }
98         void operator++() {
99             if (fRemaining) {
100                 fRemaining--;
101                 fCurr++;
102                 this->skipUninitialized();
103             }
104         }
105 
106     private:
skipUninitialized()107         void skipUninitialized() {
108             if (!fRemaining) {
109                 fCurr = nullptr;
110             } else {
111                 while (!fCurr->isInitialized()) {
112                     ++fCurr;
113                 }
114             }
115         }
116 
117         const Attribute* fCurr;
118         int fRemaining;
119     };
120 
121     class AttributeSet {
122     public:
begin()123         Iter begin() const { return Iter(fAttributes, fCount); }
end()124         Iter end() const { return Iter(); }
125 
126     private:
127         friend class GrPrimitiveProcessor;
128 
init(const Attribute * attrs,int count)129         void init(const Attribute* attrs, int count) {
130             fAttributes = attrs;
131             fRawCount = count;
132             fCount = 0;
133             fStride = 0;
134             for (int i = 0; i < count; ++i) {
135                 if (attrs[i].isInitialized()) {
136                     fCount++;
137                     fStride += attrs[i].sizeAlign4();
138                 }
139             }
140         }
141 
142         const Attribute* fAttributes = nullptr;
143         int              fRawCount = 0;
144         int              fCount = 0;
145         size_t           fStride = 0;
146     };
147 
148     GrPrimitiveProcessor(ClassID);
149 
numTextureSamplers()150     int numTextureSamplers() const { return fTextureSamplerCnt; }
151     const TextureSampler& textureSampler(int index) const;
numVertexAttributes()152     int numVertexAttributes() const { return fVertexAttributes.fCount; }
vertexAttributes()153     const AttributeSet& vertexAttributes() const { return fVertexAttributes; }
numInstanceAttributes()154     int numInstanceAttributes() const { return fInstanceAttributes.fCount; }
instanceAttributes()155     const AttributeSet& instanceAttributes() const { return fInstanceAttributes; }
156 
hasVertexAttributes()157     bool hasVertexAttributes() const { return SkToBool(fVertexAttributes.fCount); }
hasInstanceAttributes()158     bool hasInstanceAttributes() const { return SkToBool(fInstanceAttributes.fCount); }
159 
160     /**
161      * A common practice is to populate the the vertex/instance's memory using an implicit array of
162      * structs. In this case, it is best to assert that:
163      *     stride == sizeof(struct)
164      */
vertexStride()165     size_t vertexStride() const { return fVertexAttributes.fStride; }
instanceStride()166     size_t instanceStride() const { return fInstanceAttributes.fStride; }
167 
168     // Only the GrGeometryProcessor subclass actually has a geo shader or vertex attributes, but
169     // we put these calls on the base class to prevent having to cast
170     virtual bool willUseGeoShader() const = 0;
171 
172     /**
173      * Computes a transformKey from an array of coord transforms. Will only look at the first
174      * <numCoords> transforms in the array.
175      *
176      * TODO: A better name for this function  would be "compute" instead of "get".
177      */
178     uint32_t getTransformKey(const SkTArray<const GrCoordTransform*, true>& coords,
179                              int numCoords) const;
180 
181     /**
182      * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this geometry
183      * processor's GL backend implementation.
184      *
185      * TODO: A better name for this function  would be "compute" instead of "get".
186      */
187     virtual void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;
188 
189 
getAttributeKey(GrProcessorKeyBuilder * b)190     void getAttributeKey(GrProcessorKeyBuilder* b) const {
191         // Ensure that our CPU and GPU type fields fit together in a 32-bit value, and we never
192         // collide with the "uninitialized" value.
193         static_assert(kGrVertexAttribTypeCount < (1 << 8), "");
194         static_assert(kGrSLTypeCount           < (1 << 8), "");
195 
196         auto add_attributes = [=](const Attribute* attrs, int attrCount) {
197             for (int i = 0; i < attrCount; ++i) {
198                 b->add32(attrs[i].isInitialized() ? (attrs[i].cpuType() << 16) | attrs[i].gpuType()
199                                                   : ~0);
200             }
201         };
202         add_attributes(fVertexAttributes.fAttributes, fVertexAttributes.fRawCount);
203         add_attributes(fInstanceAttributes.fAttributes, fInstanceAttributes.fRawCount);
204     }
205 
206     /** Returns a new instance of the appropriate *GL* implementation class
207         for the given GrProcessor; caller is responsible for deleting
208         the object. */
209     virtual GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const = 0;
210 
isPathRendering()211     virtual bool isPathRendering() const { return false; }
212 
213 protected:
setVertexAttributes(const Attribute * attrs,int attrCount)214     void setVertexAttributes(const Attribute* attrs, int attrCount) {
215         fVertexAttributes.init(attrs, attrCount);
216     }
setInstanceAttributes(const Attribute * attrs,int attrCount)217     void setInstanceAttributes(const Attribute* attrs, int attrCount) {
218         SkASSERT(attrCount >= 0);
219         fInstanceAttributes.init(attrs, attrCount);
220     }
setTextureSamplerCnt(int cnt)221     void setTextureSamplerCnt(int cnt) {
222         SkASSERT(cnt >= 0);
223         fTextureSamplerCnt = cnt;
224     }
225 
226     /**
227      * Helper for implementing onTextureSampler(). E.g.:
228      * return IthTexureSampler(i, fMyFirstSampler, fMySecondSampler, fMyThirdSampler);
229      */
230     template <typename... Args>
IthTextureSampler(int i,const TextureSampler & samp0,const Args &...samps)231     static const TextureSampler& IthTextureSampler(int i, const TextureSampler& samp0,
232                                                    const Args&... samps) {
233         return (0 == i) ? samp0 : IthTextureSampler(i - 1, samps...);
234     }
235     inline static const TextureSampler& IthTextureSampler(int i);
236 
237 private:
onTextureSampler(int)238     virtual const TextureSampler& onTextureSampler(int) const { return IthTextureSampler(0); }
239 
240     AttributeSet fVertexAttributes;
241     AttributeSet fInstanceAttributes;
242 
243     int fTextureSamplerCnt = 0;
244     typedef GrProcessor INHERITED;
245 };
246 
247 //////////////////////////////////////////////////////////////////////////////
248 
249 /**
250  * Used to represent a texture that is required by a GrPrimitiveProcessor. It holds a GrTextureProxy
251  * along with an associated GrSamplerState. TextureSamplers don't perform any coord manipulation to
252  * account for texture origin.
253  */
254 class GrPrimitiveProcessor::TextureSampler {
255 public:
256     TextureSampler() = default;
257 
258     TextureSampler(GrTextureType, GrPixelConfig, const GrSamplerState&, uint32_t extraSamplerKey);
259 
260     explicit TextureSampler(GrTextureType, GrPixelConfig,
261                             GrSamplerState::Filter = GrSamplerState::Filter::kNearest,
262                             GrSamplerState::WrapMode wrapXAndY = GrSamplerState::WrapMode::kClamp);
263 
264     TextureSampler(const TextureSampler&) = delete;
265     TextureSampler& operator=(const TextureSampler&) = delete;
266 
267     void reset(GrTextureType, GrPixelConfig, const GrSamplerState&, uint32_t extraSamplerKey = 0);
268     void reset(GrTextureType, GrPixelConfig,
269                GrSamplerState::Filter,
270                GrSamplerState::WrapMode wrapXAndY);
271 
textureType()272     GrTextureType textureType() const { return fTextureType; }
config()273     GrPixelConfig config() const { return fConfig; }
274 
samplerState()275     const GrSamplerState& samplerState() const { return fSamplerState; }
276 
extraSamplerKey()277     uint32_t extraSamplerKey() const { return fExtraSamplerKey; }
278 
isInitialized()279     bool isInitialized() const { return fConfig != kUnknown_GrPixelConfig; }
280 
281 private:
282     GrSamplerState fSamplerState;
283     GrTextureType fTextureType = GrTextureType::k2D;
284     GrPixelConfig fConfig = kUnknown_GrPixelConfig;
285     uint32_t fExtraSamplerKey = 0;
286 };
287 
IthTextureSampler(int i)288 const GrPrimitiveProcessor::TextureSampler& GrPrimitiveProcessor::IthTextureSampler(int i) {
289     SK_ABORT("Illegal texture sampler index");
290     static const TextureSampler kBogus;
291     return kBogus;
292 }
293 
294 //////////////////////////////////////////////////////////////////////////////
295 
296 /**
297  * Returns the size of the attrib type in bytes.
298  * This was moved from include/private/GrTypesPriv.h in service of Skia dependents that build
299  * with C++11.
300  */
GrVertexAttribTypeSize(GrVertexAttribType type)301 static constexpr inline size_t GrVertexAttribTypeSize(GrVertexAttribType type) {
302     switch (type) {
303         case kFloat_GrVertexAttribType:
304             return sizeof(float);
305         case kFloat2_GrVertexAttribType:
306             return 2 * sizeof(float);
307         case kFloat3_GrVertexAttribType:
308             return 3 * sizeof(float);
309         case kFloat4_GrVertexAttribType:
310             return 4 * sizeof(float);
311         case kHalf_GrVertexAttribType:
312             return sizeof(uint16_t);
313         case kHalf2_GrVertexAttribType:
314             return 2 * sizeof(uint16_t);
315         case kHalf3_GrVertexAttribType:
316             return 3 * sizeof(uint16_t);
317         case kHalf4_GrVertexAttribType:
318             return 4 * sizeof(uint16_t);
319         case kInt2_GrVertexAttribType:
320             return 2 * sizeof(int32_t);
321         case kInt3_GrVertexAttribType:
322             return 3 * sizeof(int32_t);
323         case kInt4_GrVertexAttribType:
324             return 4 * sizeof(int32_t);
325         case kByte_GrVertexAttribType:
326             return 1 * sizeof(char);
327         case kByte2_GrVertexAttribType:
328             return 2 * sizeof(char);
329         case kByte3_GrVertexAttribType:
330             return 3 * sizeof(char);
331         case kByte4_GrVertexAttribType:
332             return 4 * sizeof(char);
333         case kUByte_GrVertexAttribType:
334             return 1 * sizeof(char);
335         case kUByte2_GrVertexAttribType:
336             return 2 * sizeof(char);
337         case kUByte3_GrVertexAttribType:
338             return 3 * sizeof(char);
339         case kUByte4_GrVertexAttribType:
340             return 4 * sizeof(char);
341         case kUByte_norm_GrVertexAttribType:
342             return 1 * sizeof(char);
343         case kUByte4_norm_GrVertexAttribType:
344             return 4 * sizeof(char);
345         case kShort2_GrVertexAttribType:
346             return 2 * sizeof(int16_t);
347         case kShort4_GrVertexAttribType:
348             return 4 * sizeof(int16_t);
349         case kUShort2_GrVertexAttribType: // fall through
350         case kUShort2_norm_GrVertexAttribType:
351             return 2 * sizeof(uint16_t);
352         case kInt_GrVertexAttribType:
353             return sizeof(int32_t);
354         case kUint_GrVertexAttribType:
355             return sizeof(uint32_t);
356     }
357     // GCC fails because SK_ABORT evaluates to non constexpr. clang and cl.exe think this is
358     // unreachable and don't complain.
359 #if defined(__clang__) || !defined(__GNUC__)
360     SK_ABORT("Unsupported type conversion");
361 #endif
362     return 0;
363 }
364 
size()365 constexpr size_t GrPrimitiveProcessor::Attribute::size() const {
366     return GrVertexAttribTypeSize(fCPUType);
367 }
368 
369 #endif
370