blob: bd769e4140e31b0dcaf36c7ff2e447c6130ef487 [file] [log] [blame]
joshualitt8072caa2015-02-12 14:20:52 -08001/*
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/*
46 * A struct for tracking batching decisions. While this lives on GrOptState, it is managed
47 * entirely by the derived classes of the GP.
48 * // TODO this was an early attempt at handling out of order batching. It should be
49 * used carefully as it is being replaced by GrBatch
50 */
51class GrBatchTracker {
52public:
53 template <typename T> const T& cast() const {
54 SkASSERT(sizeof(T) <= kMaxSize);
55 return *reinterpret_cast<const T*>(fData.get());
56 }
57
58 template <typename T> T* cast() {
59 SkASSERT(sizeof(T) <= kMaxSize);
60 return reinterpret_cast<T*>(fData.get());
61 }
62
63 static const size_t kMaxSize = 32;
64
65private:
66 SkAlignedSStorage<kMaxSize> fData;
67};
68
jvanverthe9c0fc62015-04-29 11:18:05 -070069class GrGLSLCaps;
joshualitt8072caa2015-02-12 14:20:52 -080070class GrGLPrimitiveProcessor;
joshualitt8072caa2015-02-12 14:20:52 -080071
72struct GrInitInvariantOutput;
73
74/*
bsalomon7765a472015-07-08 11:26:37 -070075 * This class allows the GrPipeline to communicate information about the pipeline to a
bsalomon91d844d2015-08-10 10:47:29 -070076 * GrBatch which should be forwarded to the GrPrimitiveProcessor(s) created by the batch.
77 * These are not properly part of the pipeline because they assume the specific inputs
78 * that the batch provided when it created the pipeline. Identical pipelines may be
79 * created by different batches with different input assumptions and therefore different
80 * computed optimizations. It is the batch-specific optimizations that allow the pipelines
81 * to be equal.
joshualitt8072caa2015-02-12 14:20:52 -080082 */
bsalomon91d844d2015-08-10 10:47:29 -070083class GrPipelineOptimizations {
bsalomon7765a472015-07-08 11:26:37 -070084public:
85 /** Does the pipeline require the GrPrimitiveProcessor's color? */
bsalomonc6998732015-08-10 12:01:15 -070086 bool readsColor() const { return SkToBool(kReadsColor_Flag & fFlags); }
bsalomon7765a472015-07-08 11:26:37 -070087
88 /** Does the pipeline require the GrPrimitiveProcessor's coverage? */
bsalomon91d844d2015-08-10 10:47:29 -070089 bool readsCoverage() const { return
bsalomonc6998732015-08-10 12:01:15 -070090 SkToBool(kReadsCoverage_Flag & fFlags); }
bsalomon7765a472015-07-08 11:26:37 -070091
92 /** Does the pipeline require access to (implicit or explicit) local coordinates? */
93 bool readsLocalCoords() const {
bsalomonc6998732015-08-10 12:01:15 -070094 return SkToBool(kReadsLocalCoords_Flag & fFlags);
bsalomon7765a472015-07-08 11:26:37 -070095 }
96
97 /** Does the pipeline allow the GrPrimitiveProcessor to combine color and coverage into one
98 color output ? */
99 bool canTweakAlphaForCoverage() const {
bsalomonc6998732015-08-10 12:01:15 -0700100 return SkToBool(kCanTweakAlphaForCoverage_Flag & fFlags);
bsalomon7765a472015-07-08 11:26:37 -0700101 }
102
103 /** Does the pipeline require the GrPrimitiveProcessor to specify a specific color (and if
104 so get the color)? */
105 bool getOverrideColorIfSet(GrColor* overrideColor) const {
bsalomonc6998732015-08-10 12:01:15 -0700106 if (SkToBool(kUseOverrideColor_Flag & fFlags)) {
107 SkASSERT(SkToBool(kReadsColor_Flag & fFlags));
bsalomon7765a472015-07-08 11:26:37 -0700108 if (overrideColor) {
109 *overrideColor = fOverrideColor;
110 }
111 return true;
112 }
113 return false;
114 }
115
bsalomon2d563032015-08-13 07:08:31 -0700116 /**
117 * Returns true if the pipeline's color output will be affected by the existing render target
118 * destination pixel values (meaning we need to be careful with overlapping draws). Note that we
119 * can conflate coverage and color, so the destination color may still bleed into pixels that
120 * have partial coverage, even if this function returns false.
121 *
122 * The above comment seems incorrect for the use case. This funciton is used to turn two
123 * overlapping draws into a single draw (really to stencil multiple paths and do a single
124 * cover). It seems that what really matters is whether the dst is read for color OR for
125 * coverage.
126 */
127 bool willColorBlendWithDst() const { return SkToBool(kWillColorBlendWithDst_Flag & fFlags); }
128
bsalomon7765a472015-07-08 11:26:37 -0700129private:
130 enum {
131 // If this is not set the primitive processor need not produce a color output
bsalomonc6998732015-08-10 12:01:15 -0700132 kReadsColor_Flag = 0x1,
bsalomon7765a472015-07-08 11:26:37 -0700133
134 // If this is not set the primitive processor need not produce a coverage output
bsalomonc6998732015-08-10 12:01:15 -0700135 kReadsCoverage_Flag = 0x2,
bsalomon7765a472015-07-08 11:26:37 -0700136
137 // If this is not set the primitive processor need not produce local coordinates
bsalomonc6998732015-08-10 12:01:15 -0700138 kReadsLocalCoords_Flag = 0x4,
bsalomon7765a472015-07-08 11:26:37 -0700139
140 // If this flag is set then the primitive processor may produce color*coverage as
141 // its color output (and not output a separate coverage).
bsalomonc6998732015-08-10 12:01:15 -0700142 kCanTweakAlphaForCoverage_Flag = 0x8,
bsalomon7765a472015-07-08 11:26:37 -0700143
144 // If this flag is set the GrPrimitiveProcessor must produce fOverrideColor as its
145 // output color. If not set fOverrideColor is to be ignored.
bsalomonc6998732015-08-10 12:01:15 -0700146 kUseOverrideColor_Flag = 0x10,
bsalomon2d563032015-08-13 07:08:31 -0700147
148 kWillColorBlendWithDst_Flag = 0x20,
bsalomon7765a472015-07-08 11:26:37 -0700149 };
150
151 uint32_t fFlags;
152 GrColor fOverrideColor;
153
154 friend class GrPipeline; // To initialize this
joshualitt8072caa2015-02-12 14:20:52 -0800155};
156
157/*
158 * This enum is shared by GrPrimitiveProcessors and GrGLPrimitiveProcessors to coordinate shaders
159 * with vertex attributes / uniforms.
160 */
161enum GrGPInput {
162 kAllOnes_GrGPInput,
163 kAttribute_GrGPInput,
164 kUniform_GrGPInput,
165 kIgnored_GrGPInput,
166};
167
168/*
169 * GrPrimitiveProcessor defines an interface which all subclasses must implement. All
170 * GrPrimitiveProcessors must proivide seed color and coverage for the Ganesh color / coverage
171 * pipelines, and they must provide some notion of equality
172 */
173class GrPrimitiveProcessor : public GrProcessor {
174public:
bsalomon91d844d2015-08-10 10:47:29 -0700175 virtual void initBatchTracker(GrBatchTracker*, const GrPipelineOptimizations&) const = 0;
joshualitt8072caa2015-02-12 14:20:52 -0800176
177 virtual bool canMakeEqual(const GrBatchTracker& mine,
178 const GrPrimitiveProcessor& that,
179 const GrBatchTracker& theirs) const = 0;
180
181 virtual void getInvariantOutputColor(GrInitInvariantOutput* out) const = 0;
182 virtual void getInvariantOutputCoverage(GrInitInvariantOutput* out) const = 0;
183
184 // Only the GrGeometryProcessor subclass actually has a geo shader or vertex attributes, but
185 // we put these calls on the base class to prevent having to cast
186 virtual bool willUseGeoShader() const = 0;
187
188 /*
189 * This is a safeguard to prevent GrPrimitiveProcessor's from going beyond platform specific
190 * attribute limits. This number can almost certainly be raised if required.
191 */
192 static const int kMaxVertexAttribs = 6;
193
194 struct Attribute {
195 Attribute()
halcanary96fcdcc2015-08-27 07:41:13 -0700196 : fName(nullptr)
joshualitt8072caa2015-02-12 14:20:52 -0800197 , fType(kFloat_GrVertexAttribType)
198 , fOffset(0) {}
senorblancof2539d52015-05-20 14:03:42 -0700199 Attribute(const char* name, GrVertexAttribType type,
200 GrSLPrecision precision = kDefault_GrSLPrecision)
joshualitt8072caa2015-02-12 14:20:52 -0800201 : fName(name)
202 , fType(type)
senorblancof2539d52015-05-20 14:03:42 -0700203 , fOffset(SkAlign4(GrVertexAttribTypeSize(type)))
204 , fPrecision(precision) {}
joshualitt8072caa2015-02-12 14:20:52 -0800205 const char* fName;
206 GrVertexAttribType fType;
207 size_t fOffset;
senorblancof2539d52015-05-20 14:03:42 -0700208 GrSLPrecision fPrecision;
joshualitt8072caa2015-02-12 14:20:52 -0800209 };
210
211 int numAttribs() const { return fNumAttribs; }
212 const Attribute& getAttrib(int index) const {
213 SkASSERT(index < fNumAttribs);
214 return fAttribs[index];
215 }
216
217 // Returns the vertex stride of the GP. A common use case is to request geometry from a
218 // drawtarget based off of the stride, and to populate this memory using an implicit array of
219 // structs. In this case, it is best to assert the vertexstride == sizeof(VertexStruct).
220 size_t getVertexStride() const { return fVertexStride; }
221
222 /**
wangyixa7f4c432015-08-20 07:25:02 -0700223 * Computes a transformKey from an array of coord transforms. Will only look at the first
224 * <numCoords> transforms in the array.
225 *
226 * TODO: A better name for this function would be "compute" instead of "get".
joshualitt8072caa2015-02-12 14:20:52 -0800227 */
wangyixa7f4c432015-08-20 07:25:02 -0700228 uint32_t getTransformKey(const SkTArray<const GrCoordTransform*, true>& coords,
229 int numCoords) const;
joshualitt8072caa2015-02-12 14:20:52 -0800230
231 /**
232 * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this geometry
233 * processor's GL backend implementation.
wangyixa7f4c432015-08-20 07:25:02 -0700234 *
235 * TODO: A better name for this function would be "compute" instead of "get".
joshualitt8072caa2015-02-12 14:20:52 -0800236 */
237 virtual void getGLProcessorKey(const GrBatchTracker& bt,
jvanverthcfc18862015-04-28 08:48:20 -0700238 const GrGLSLCaps& caps,
joshualitt8072caa2015-02-12 14:20:52 -0800239 GrProcessorKeyBuilder* b) const = 0;
240
241
242 /** Returns a new instance of the appropriate *GL* implementation class
243 for the given GrProcessor; caller is responsible for deleting
244 the object. */
245 virtual GrGLPrimitiveProcessor* createGLInstance(const GrBatchTracker& bt,
jvanverthcfc18862015-04-28 08:48:20 -0700246 const GrGLSLCaps& caps) const = 0;
joshualitt8072caa2015-02-12 14:20:52 -0800247
248 bool isPathRendering() const { return fIsPathRendering; }
249
joshualittb2aa7cb2015-08-05 11:05:22 -0700250 /**
251 * No Local Coord Transformation is needed in the shader, instead transformed local coords will
252 * be provided via vertex attribute.
253 */
254 virtual bool hasTransformedLocalCoords() const = 0;
255
joshualitt8072caa2015-02-12 14:20:52 -0800256protected:
joshualitte3ababe2015-05-15 07:56:07 -0700257 GrPrimitiveProcessor(bool isPathRendering)
joshualitt8072caa2015-02-12 14:20:52 -0800258 : fNumAttribs(0)
259 , fVertexStride(0)
joshualitt8072caa2015-02-12 14:20:52 -0800260 , fIsPathRendering(isPathRendering) {}
261
joshualitt8072caa2015-02-12 14:20:52 -0800262 Attribute fAttribs[kMaxVertexAttribs];
263 int fNumAttribs;
264 size_t fVertexStride;
265
266private:
267 virtual bool hasExplicitLocalCoords() const = 0;
268
joshualitt8072caa2015-02-12 14:20:52 -0800269 bool fIsPathRendering;
270
271 typedef GrProcessor INHERITED;
272};
273
274#endif