blob: ea1237b9a2ac569f49bf8f69a286c47e1bd946ff [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
69class GrIndexBufferAllocPool;
70class GrGLCaps;
jvanverthcfc18862015-04-28 08:48:20 -070071typedef GrGLCaps GrGLSLCaps;
joshualitt8072caa2015-02-12 14:20:52 -080072class GrGLPrimitiveProcessor;
73class GrVertexBufferAllocPool;
74
75struct GrInitInvariantOutput;
76
77/*
78 * This struct allows the GrPipeline to communicate information about the pipeline. Most of this
79 * is overrides, but some of it is general information. Logically it should live in GrPipeline.h,
80 * but this is problematic due to circular dependencies.
81 */
82struct GrPipelineInfo {
83 bool fColorIgnored;
84 bool fCoverageIgnored;
85 GrColor fOverrideColor;
86 bool fUsesLocalCoords;
egdanielf7c2d552015-02-13 12:11:00 -080087 bool fCanTweakAlphaForCoverage;
joshualitt8072caa2015-02-12 14:20:52 -080088};
89
90/*
91 * This enum is shared by GrPrimitiveProcessors and GrGLPrimitiveProcessors to coordinate shaders
92 * with vertex attributes / uniforms.
93 */
94enum GrGPInput {
95 kAllOnes_GrGPInput,
96 kAttribute_GrGPInput,
97 kUniform_GrGPInput,
98 kIgnored_GrGPInput,
99};
100
101/*
102 * GrPrimitiveProcessor defines an interface which all subclasses must implement. All
103 * GrPrimitiveProcessors must proivide seed color and coverage for the Ganesh color / coverage
104 * pipelines, and they must provide some notion of equality
105 */
106class GrPrimitiveProcessor : public GrProcessor {
107public:
108 // TODO let the PrimProc itself set this in its setData call, this should really live on the
109 // bundle of primitive data
110 const SkMatrix& viewMatrix() const { return fViewMatrix; }
111 const SkMatrix& localMatrix() const { return fLocalMatrix; }
112
113 virtual void initBatchTracker(GrBatchTracker*, const GrPipelineInfo&) const = 0;
114
115 virtual bool canMakeEqual(const GrBatchTracker& mine,
116 const GrPrimitiveProcessor& that,
117 const GrBatchTracker& theirs) const = 0;
118
119 virtual void getInvariantOutputColor(GrInitInvariantOutput* out) const = 0;
120 virtual void getInvariantOutputCoverage(GrInitInvariantOutput* out) const = 0;
121
122 // Only the GrGeometryProcessor subclass actually has a geo shader or vertex attributes, but
123 // we put these calls on the base class to prevent having to cast
124 virtual bool willUseGeoShader() const = 0;
125
126 /*
127 * This is a safeguard to prevent GrPrimitiveProcessor's from going beyond platform specific
128 * attribute limits. This number can almost certainly be raised if required.
129 */
130 static const int kMaxVertexAttribs = 6;
131
132 struct Attribute {
133 Attribute()
134 : fName(NULL)
135 , fType(kFloat_GrVertexAttribType)
136 , fOffset(0) {}
137 Attribute(const char* name, GrVertexAttribType type)
138 : fName(name)
139 , fType(type)
140 , fOffset(SkAlign4(GrVertexAttribTypeSize(type))) {}
141 const char* fName;
142 GrVertexAttribType fType;
143 size_t fOffset;
144 };
145
146 int numAttribs() const { return fNumAttribs; }
147 const Attribute& getAttrib(int index) const {
148 SkASSERT(index < fNumAttribs);
149 return fAttribs[index];
150 }
151
152 // Returns the vertex stride of the GP. A common use case is to request geometry from a
153 // drawtarget based off of the stride, and to populate this memory using an implicit array of
154 // structs. In this case, it is best to assert the vertexstride == sizeof(VertexStruct).
155 size_t getVertexStride() const { return fVertexStride; }
156
157 /**
158 * Gets a transformKey from an array of coord transforms
159 */
160 uint32_t getTransformKey(const SkTArray<const GrCoordTransform*, true>&) const;
161
162 /**
163 * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this geometry
164 * processor's GL backend implementation.
165 */
166 virtual void getGLProcessorKey(const GrBatchTracker& bt,
jvanverthcfc18862015-04-28 08:48:20 -0700167 const GrGLSLCaps& caps,
joshualitt8072caa2015-02-12 14:20:52 -0800168 GrProcessorKeyBuilder* b) const = 0;
169
170
171 /** Returns a new instance of the appropriate *GL* implementation class
172 for the given GrProcessor; caller is responsible for deleting
173 the object. */
174 virtual GrGLPrimitiveProcessor* createGLInstance(const GrBatchTracker& bt,
jvanverthcfc18862015-04-28 08:48:20 -0700175 const GrGLSLCaps& caps) const = 0;
joshualitt8072caa2015-02-12 14:20:52 -0800176
177 bool isPathRendering() const { return fIsPathRendering; }
178
179protected:
180 GrPrimitiveProcessor(const SkMatrix& viewMatrix, const SkMatrix& localMatrix,
181 bool isPathRendering)
182 : fNumAttribs(0)
183 , fVertexStride(0)
184 , fViewMatrix(viewMatrix)
185 , fLocalMatrix(localMatrix)
186 , fIsPathRendering(isPathRendering) {}
187
188 /*
189 * CanCombineOutput will return true if two draws are 'batchable' from a color perspective.
190 * TODO remove this when GPs can upgrade to attribute color
191 */
192 static bool CanCombineOutput(GrGPInput left, GrColor lColor, GrGPInput right, GrColor rColor) {
193 if (left != right) {
194 return false;
195 }
196
197 if (kUniform_GrGPInput == left && lColor != rColor) {
198 return false;
199 }
200
201 return true;
202 }
203
204 static bool CanCombineLocalMatrices(const GrPrimitiveProcessor& left,
205 bool leftUsesLocalCoords,
206 const GrPrimitiveProcessor& right,
207 bool rightUsesLocalCoords) {
208 if (leftUsesLocalCoords != rightUsesLocalCoords) {
209 return false;
210 }
211
212 if (leftUsesLocalCoords && !left.localMatrix().cheapEqualTo(right.localMatrix())) {
213 return false;
214 }
215 return true;
216 }
217
218 Attribute fAttribs[kMaxVertexAttribs];
219 int fNumAttribs;
220 size_t fVertexStride;
221
222private:
223 virtual bool hasExplicitLocalCoords() const = 0;
224
225 const SkMatrix fViewMatrix;
226 SkMatrix fLocalMatrix;
227 bool fIsPathRendering;
228
229 typedef GrProcessor INHERITED;
230};
231
232#endif