1 /*
2 * Copyright 2014 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 #include "GrDefaultGeoProcFactory.h"
9
10 #include "GrInvariantOutput.h"
11 #include "glsl/GrGLSLFragmentShaderBuilder.h"
12 #include "glsl/GrGLSLGeometryProcessor.h"
13 #include "glsl/GrGLSLVertexShaderBuilder.h"
14 #include "glsl/GrGLSLVarying.h"
15 #include "glsl/GrGLSLUniformHandler.h"
16 #include "glsl/GrGLSLUtil.h"
17
18 /*
19 * The default Geometry Processor simply takes position and multiplies it by the uniform view
20 * matrix. It also leaves coverage untouched. Behind the scenes, we may add per vertex color or
21 * local coords.
22 */
23
24 enum GPFlag {
25 kColor_GPFlag = 0x1,
26 kLocalCoord_GPFlag = 0x2,
27 kCoverage_GPFlag= 0x4,
28 kTransformedLocalCoord_GPFlag = 0x8,
29 };
30
31 class DefaultGeoProc : public GrGeometryProcessor {
32 public:
Create(uint32_t gpTypeFlags,GrColor color,const SkMatrix & viewMatrix,const SkMatrix & localMatrix,bool localCoordsWillBeRead,bool coverageWillBeIgnored,uint8_t coverage)33 static GrGeometryProcessor* Create(uint32_t gpTypeFlags,
34 GrColor color,
35 const SkMatrix& viewMatrix,
36 const SkMatrix& localMatrix,
37 bool localCoordsWillBeRead,
38 bool coverageWillBeIgnored,
39 uint8_t coverage) {
40 return new DefaultGeoProc(gpTypeFlags, color, viewMatrix, localMatrix, coverage,
41 localCoordsWillBeRead, coverageWillBeIgnored);
42 }
43
name() const44 const char* name() const override { return "DefaultGeometryProcessor"; }
45
inPosition() const46 const Attribute* inPosition() const { return fInPosition; }
inColor() const47 const Attribute* inColor() const { return fInColor; }
inLocalCoords() const48 const Attribute* inLocalCoords() const { return fInLocalCoords; }
inCoverage() const49 const Attribute* inCoverage() const { return fInCoverage; }
color() const50 GrColor color() const { return fColor; }
colorIgnored() const51 bool colorIgnored() const { return GrColor_ILLEGAL == fColor; }
hasVertexColor() const52 bool hasVertexColor() const { return SkToBool(fInColor); }
viewMatrix() const53 const SkMatrix& viewMatrix() const { return fViewMatrix; }
localMatrix() const54 const SkMatrix& localMatrix() const { return fLocalMatrix; }
localCoordsWillBeRead() const55 bool localCoordsWillBeRead() const { return fLocalCoordsWillBeRead; }
coverage() const56 uint8_t coverage() const { return fCoverage; }
coverageWillBeIgnored() const57 bool coverageWillBeIgnored() const { return fCoverageWillBeIgnored; }
hasVertexCoverage() const58 bool hasVertexCoverage() const { return SkToBool(fInCoverage); }
59
60 class GLSLProcessor : public GrGLSLGeometryProcessor {
61 public:
GLSLProcessor()62 GLSLProcessor()
63 : fViewMatrix(SkMatrix::InvalidMatrix()), fColor(GrColor_ILLEGAL), fCoverage(0xff) {}
64
onEmitCode(EmitArgs & args,GrGPArgs * gpArgs)65 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
66 const DefaultGeoProc& gp = args.fGP.cast<DefaultGeoProc>();
67 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
68 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
69 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
70 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
71
72 // emit attributes
73 varyingHandler->emitAttributes(gp);
74
75 // Setup pass through color
76 if (!gp.colorIgnored()) {
77 if (gp.hasVertexColor()) {
78 varyingHandler->addPassThroughAttribute(gp.inColor(), args.fOutputColor);
79 } else {
80 this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor,
81 &fColorUniform);
82 }
83 }
84
85 // Setup position
86 this->setupPosition(vertBuilder,
87 uniformHandler,
88 gpArgs,
89 gp.inPosition()->fName,
90 gp.viewMatrix(),
91 &fViewMatrixUniform);
92
93 if (gp.hasExplicitLocalCoords()) {
94 // emit transforms with explicit local coords
95 this->emitTransforms(vertBuilder,
96 varyingHandler,
97 uniformHandler,
98 gpArgs->fPositionVar,
99 gp.inLocalCoords()->fName,
100 gp.localMatrix(),
101 args.fTransformsIn,
102 args.fTransformsOut);
103 } else if(gp.hasTransformedLocalCoords()) {
104 // transforms have already been applied to vertex attributes on the cpu
105 this->emitTransforms(vertBuilder,
106 varyingHandler,
107 gp.inLocalCoords()->fName,
108 args.fTransformsIn,
109 args.fTransformsOut);
110 } else {
111 // emit transforms with position
112 this->emitTransforms(vertBuilder,
113 varyingHandler,
114 uniformHandler,
115 gpArgs->fPositionVar,
116 gp.inPosition()->fName,
117 gp.localMatrix(),
118 args.fTransformsIn,
119 args.fTransformsOut);
120 }
121
122 // Setup coverage as pass through
123 if (!gp.coverageWillBeIgnored()) {
124 if (gp.hasVertexCoverage()) {
125 fragBuilder->codeAppendf("float alpha = 1.0;");
126 varyingHandler->addPassThroughAttribute(gp.inCoverage(), "alpha");
127 fragBuilder->codeAppendf("%s = vec4(alpha);", args.fOutputCoverage);
128 } else if (gp.coverage() == 0xff) {
129 fragBuilder->codeAppendf("%s = vec4(1);", args.fOutputCoverage);
130 } else {
131 const char* fragCoverage;
132 fCoverageUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
133 kFloat_GrSLType,
134 kDefault_GrSLPrecision,
135 "Coverage",
136 &fragCoverage);
137 fragBuilder->codeAppendf("%s = vec4(%s);", args.fOutputCoverage, fragCoverage);
138 }
139 }
140 }
141
GenKey(const GrGeometryProcessor & gp,const GrGLSLCaps &,GrProcessorKeyBuilder * b)142 static inline void GenKey(const GrGeometryProcessor& gp,
143 const GrGLSLCaps&,
144 GrProcessorKeyBuilder* b) {
145 const DefaultGeoProc& def = gp.cast<DefaultGeoProc>();
146 uint32_t key = def.fFlags;
147 key |= def.colorIgnored() << 8;
148 key |= def.coverageWillBeIgnored() << 9;
149 key |= def.hasVertexColor() << 10;
150 key |= def.hasVertexCoverage() << 11;
151 key |= def.coverage() == 0xff ? 0x1 << 12 : 0;
152 key |= def.localCoordsWillBeRead() && def.localMatrix().hasPerspective() ? 0x1 << 24 :
153 0x0;
154 key |= ComputePosKey(def.viewMatrix()) << 25;
155 b->add32(key);
156 }
157
setData(const GrGLSLProgramDataManager & pdman,const GrPrimitiveProcessor & gp)158 void setData(const GrGLSLProgramDataManager& pdman,
159 const GrPrimitiveProcessor& gp) override {
160 const DefaultGeoProc& dgp = gp.cast<DefaultGeoProc>();
161
162 if (!dgp.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(dgp.viewMatrix())) {
163 fViewMatrix = dgp.viewMatrix();
164 float viewMatrix[3 * 3];
165 GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
166 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
167 }
168
169 if (dgp.color() != fColor && !dgp.hasVertexColor()) {
170 float c[4];
171 GrColorToRGBAFloat(dgp.color(), c);
172 pdman.set4fv(fColorUniform, 1, c);
173 fColor = dgp.color();
174 }
175
176 if (!dgp.coverageWillBeIgnored() &&
177 dgp.coverage() != fCoverage && !dgp.hasVertexCoverage()) {
178 pdman.set1f(fCoverageUniform, GrNormalizeByteToFloat(dgp.coverage()));
179 fCoverage = dgp.coverage();
180 }
181 }
182
setTransformData(const GrPrimitiveProcessor & primProc,const GrGLSLProgramDataManager & pdman,int index,const SkTArray<const GrCoordTransform *,true> & transforms)183 void setTransformData(const GrPrimitiveProcessor& primProc,
184 const GrGLSLProgramDataManager& pdman,
185 int index,
186 const SkTArray<const GrCoordTransform*, true>& transforms) override {
187 this->setTransformDataHelper<DefaultGeoProc>(primProc, pdman, index, transforms);
188 }
189
190 private:
191 SkMatrix fViewMatrix;
192 GrColor fColor;
193 uint8_t fCoverage;
194 UniformHandle fViewMatrixUniform;
195 UniformHandle fColorUniform;
196 UniformHandle fCoverageUniform;
197
198 typedef GrGLSLGeometryProcessor INHERITED;
199 };
200
getGLSLProcessorKey(const GrGLSLCaps & caps,GrProcessorKeyBuilder * b) const201 void getGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
202 GLSLProcessor::GenKey(*this, caps, b);
203 }
204
createGLSLInstance(const GrGLSLCaps &) const205 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrGLSLCaps&) const override {
206 return new GLSLProcessor();
207 }
208
209 private:
DefaultGeoProc(uint32_t gpTypeFlags,GrColor color,const SkMatrix & viewMatrix,const SkMatrix & localMatrix,uint8_t coverage,bool localCoordsWillBeRead,bool coverageWillBeIgnored)210 DefaultGeoProc(uint32_t gpTypeFlags,
211 GrColor color,
212 const SkMatrix& viewMatrix,
213 const SkMatrix& localMatrix,
214 uint8_t coverage,
215 bool localCoordsWillBeRead,
216 bool coverageWillBeIgnored)
217 : fInPosition(nullptr)
218 , fInColor(nullptr)
219 , fInLocalCoords(nullptr)
220 , fInCoverage(nullptr)
221 , fColor(color)
222 , fViewMatrix(viewMatrix)
223 , fLocalMatrix(localMatrix)
224 , fCoverage(coverage)
225 , fFlags(gpTypeFlags)
226 , fLocalCoordsWillBeRead(localCoordsWillBeRead)
227 , fCoverageWillBeIgnored(coverageWillBeIgnored) {
228 this->initClassID<DefaultGeoProc>();
229 bool hasColor = SkToBool(gpTypeFlags & kColor_GPFlag);
230 bool hasExplicitLocalCoords = SkToBool(gpTypeFlags & kLocalCoord_GPFlag);
231 bool hasTransformedLocalCoords = SkToBool(gpTypeFlags & kTransformedLocalCoord_GPFlag);
232 bool hasLocalCoord = hasExplicitLocalCoords || hasTransformedLocalCoords;
233 bool hasCoverage = SkToBool(gpTypeFlags & kCoverage_GPFlag);
234 fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType,
235 kHigh_GrSLPrecision));
236 if (hasColor) {
237 fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexAttribType));
238 }
239 if (hasLocalCoord) {
240 fInLocalCoords = &this->addVertexAttrib(Attribute("inLocalCoord",
241 kVec2f_GrVertexAttribType));
242 if (hasExplicitLocalCoords) {
243 this->setHasExplicitLocalCoords();
244 } else {
245 SkASSERT(hasTransformedLocalCoords);
246 this->setHasTransformedLocalCoords();
247 }
248 }
249 if (hasCoverage) {
250 fInCoverage = &this->addVertexAttrib(Attribute("inCoverage",
251 kFloat_GrVertexAttribType));
252 }
253 }
254
255 const Attribute* fInPosition;
256 const Attribute* fInColor;
257 const Attribute* fInLocalCoords;
258 const Attribute* fInCoverage;
259 GrColor fColor;
260 SkMatrix fViewMatrix;
261 SkMatrix fLocalMatrix;
262 uint8_t fCoverage;
263 uint32_t fFlags;
264 bool fLocalCoordsWillBeRead;
265 bool fCoverageWillBeIgnored;
266
267 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
268
269 typedef GrGeometryProcessor INHERITED;
270 };
271
272 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DefaultGeoProc);
273
TestCreate(GrProcessorTestData * d)274 const GrGeometryProcessor* DefaultGeoProc::TestCreate(GrProcessorTestData* d) {
275 uint32_t flags = 0;
276 if (d->fRandom->nextBool()) {
277 flags |= kColor_GPFlag;
278 }
279 if (d->fRandom->nextBool()) {
280 flags |= kCoverage_GPFlag;
281 }
282 if (d->fRandom->nextBool()) {
283 flags |= kLocalCoord_GPFlag;
284 }
285 if (d->fRandom->nextBool()) {
286 flags |= kTransformedLocalCoord_GPFlag;
287 }
288
289 return DefaultGeoProc::Create(flags,
290 GrRandomColor(d->fRandom),
291 GrTest::TestMatrix(d->fRandom),
292 GrTest::TestMatrix(d->fRandom),
293 d->fRandom->nextBool(),
294 d->fRandom->nextBool(),
295 GrRandomCoverage(d->fRandom));
296 }
297
Create(const Color & color,const Coverage & coverage,const LocalCoords & localCoords,const SkMatrix & viewMatrix)298 const GrGeometryProcessor* GrDefaultGeoProcFactory::Create(const Color& color,
299 const Coverage& coverage,
300 const LocalCoords& localCoords,
301 const SkMatrix& viewMatrix) {
302 uint32_t flags = 0;
303 flags |= color.fType == Color::kAttribute_Type ? kColor_GPFlag : 0;
304 flags |= coverage.fType == Coverage::kAttribute_Type ? kCoverage_GPFlag : 0;
305 flags |= localCoords.fType == LocalCoords::kHasExplicit_Type ? kLocalCoord_GPFlag : 0;
306 flags |= localCoords.fType == LocalCoords::kHasTransformed_Type ?
307 kTransformedLocalCoord_GPFlag : 0;
308
309 uint8_t inCoverage = coverage.fCoverage;
310 bool coverageWillBeIgnored = coverage.fType == Coverage::kNone_Type;
311 bool localCoordsWillBeRead = localCoords.fType != LocalCoords::kUnused_Type;
312
313 GrColor inColor = color.fColor;
314 return DefaultGeoProc::Create(flags,
315 inColor,
316 viewMatrix,
317 localCoords.fMatrix ? *localCoords.fMatrix : SkMatrix::I(),
318 localCoordsWillBeRead,
319 coverageWillBeIgnored,
320 inCoverage);
321 }
322
CreateForDeviceSpace(const Color & color,const Coverage & coverage,const LocalCoords & localCoords,const SkMatrix & viewMatrix)323 const GrGeometryProcessor* GrDefaultGeoProcFactory::CreateForDeviceSpace(
324 const Color& color,
325 const Coverage& coverage,
326 const LocalCoords& localCoords,
327 const SkMatrix& viewMatrix) {
328 SkMatrix invert = SkMatrix::I();
329 if (LocalCoords::kUnused_Type != localCoords.fType) {
330 SkASSERT(LocalCoords::kUsePosition_Type == localCoords.fType);
331 if (!viewMatrix.isIdentity() && !viewMatrix.invert(&invert)) {
332 SkDebugf("Could not invert\n");
333 return nullptr;
334 }
335
336 if (localCoords.hasLocalMatrix()) {
337 invert.preConcat(*localCoords.fMatrix);
338 }
339 }
340
341 LocalCoords inverted(LocalCoords::kUsePosition_Type, &invert);
342 return Create(color, coverage, inverted, SkMatrix::I());
343 }
344