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 #include "GrBezierEffect.h"
9 #include "GrShaderCaps.h"
10 #include "glsl/GrGLSLFragmentShaderBuilder.h"
11 #include "glsl/GrGLSLGeometryProcessor.h"
12 #include "glsl/GrGLSLProgramDataManager.h"
13 #include "glsl/GrGLSLUniformHandler.h"
14 #include "glsl/GrGLSLUtil.h"
15 #include "glsl/GrGLSLVarying.h"
16 #include "glsl/GrGLSLVertexShaderBuilder.h"
17
18 class GrGLConicEffect : public GrGLSLGeometryProcessor {
19 public:
20 GrGLConicEffect(const GrGeometryProcessor&);
21
22 void onEmitCode(EmitArgs&, GrGPArgs*) override;
23
24 static inline void GenKey(const GrGeometryProcessor&,
25 const GrShaderCaps&,
26 GrProcessorKeyBuilder*);
27
setData(const GrGLSLProgramDataManager & pdman,const GrPrimitiveProcessor & primProc,FPCoordTransformIter && transformIter)28 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc,
29 FPCoordTransformIter&& transformIter) override {
30 const GrConicEffect& ce = primProc.cast<GrConicEffect>();
31
32 if (!ce.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(ce.viewMatrix())) {
33 fViewMatrix = ce.viewMatrix();
34 float viewMatrix[3 * 3];
35 GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
36 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
37 }
38
39 if (ce.color() != fColor) {
40 float c[4];
41 GrColorToRGBAFloat(ce.color(), c);
42 pdman.set4fv(fColorUniform, 1, c);
43 fColor = ce.color();
44 }
45
46 if (ce.coverageScale() != 0xff && ce.coverageScale() != fCoverageScale) {
47 pdman.set1f(fCoverageScaleUniform, GrNormalizeByteToFloat(ce.coverageScale()));
48 fCoverageScale = ce.coverageScale();
49 }
50 this->setTransformDataHelper(ce.localMatrix(), pdman, &transformIter);
51 }
52
53 private:
54 SkMatrix fViewMatrix;
55 GrColor fColor;
56 uint8_t fCoverageScale;
57 GrPrimitiveEdgeType fEdgeType;
58 UniformHandle fColorUniform;
59 UniformHandle fCoverageScaleUniform;
60 UniformHandle fViewMatrixUniform;
61
62 typedef GrGLSLGeometryProcessor INHERITED;
63 };
64
GrGLConicEffect(const GrGeometryProcessor & processor)65 GrGLConicEffect::GrGLConicEffect(const GrGeometryProcessor& processor)
66 : fViewMatrix(SkMatrix::InvalidMatrix()), fColor(GrColor_ILLEGAL), fCoverageScale(0xff) {
67 const GrConicEffect& ce = processor.cast<GrConicEffect>();
68 fEdgeType = ce.getEdgeType();
69 }
70
onEmitCode(EmitArgs & args,GrGPArgs * gpArgs)71 void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
72 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
73 const GrConicEffect& gp = args.fGP.cast<GrConicEffect>();
74 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
75 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
76
77 // emit attributes
78 varyingHandler->emitAttributes(gp);
79
80 GrGLSLVertToFrag v(kVec4f_GrSLType);
81 varyingHandler->addVarying("ConicCoeffs", &v, kHigh_GrSLPrecision);
82 vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inConicCoeffs()->fName);
83
84 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
85 // Setup pass through color
86 this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform);
87
88 // Setup position
89 this->setupPosition(vertBuilder,
90 uniformHandler,
91 gpArgs,
92 gp.inPosition()->fName,
93 gp.viewMatrix(),
94 &fViewMatrixUniform);
95
96 // emit transforms with position
97 this->emitTransforms(vertBuilder,
98 varyingHandler,
99 uniformHandler,
100 gpArgs->fPositionVar,
101 gp.inPosition()->fName,
102 gp.localMatrix(),
103 args.fFPCoordTransformHandler);
104
105 // TODO: this precision check should actually be a check on the number of bits
106 // high and medium provide and the selection of the lowest level that suffices.
107 // Additionally we should assert that the upstream code only lets us get here if
108 // either high or medium provides the required number of bits.
109 GrSLPrecision precision = kHigh_GrSLPrecision;
110 const GrShaderCaps::PrecisionInfo& highP = args.fShaderCaps->getFloatShaderPrecisionInfo(
111 kFragment_GrShaderType,
112 kHigh_GrSLPrecision);
113 if (!highP.supported()) {
114 precision = kMedium_GrSLPrecision;
115 }
116
117 GrShaderVar edgeAlpha("edgeAlpha", kFloat_GrSLType, 0, precision);
118 GrShaderVar dklmdx("dklmdx", kVec3f_GrSLType, 0, precision);
119 GrShaderVar dklmdy("dklmdy", kVec3f_GrSLType, 0, precision);
120 GrShaderVar dfdx("dfdx", kFloat_GrSLType, 0, precision);
121 GrShaderVar dfdy("dfdy", kFloat_GrSLType, 0, precision);
122 GrShaderVar gF("gF", kVec2f_GrSLType, 0, precision);
123 GrShaderVar gFM("gFM", kFloat_GrSLType, 0, precision);
124 GrShaderVar func("func", kFloat_GrSLType, 0, precision);
125
126 fragBuilder->declAppend(edgeAlpha);
127 fragBuilder->declAppend(dklmdx);
128 fragBuilder->declAppend(dklmdy);
129 fragBuilder->declAppend(dfdx);
130 fragBuilder->declAppend(dfdy);
131 fragBuilder->declAppend(gF);
132 fragBuilder->declAppend(gFM);
133 fragBuilder->declAppend(func);
134
135 switch (fEdgeType) {
136 case kHairlineAA_GrProcessorEdgeType: {
137 fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn());
138 fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn());
139 fragBuilder->codeAppendf("%s = 2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
140 dfdx.c_str(),
141 v.fsIn(), dklmdx.c_str(),
142 v.fsIn(), dklmdx.c_str(),
143 v.fsIn(), dklmdx.c_str());
144 fragBuilder->codeAppendf("%s = 2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
145 dfdy.c_str(),
146 v.fsIn(), dklmdy.c_str(),
147 v.fsIn(), dklmdy.c_str(),
148 v.fsIn(), dklmdy.c_str());
149 fragBuilder->codeAppendf("%s = vec2(%s, %s);", gF.c_str(), dfdx.c_str(), dfdy.c_str());
150 fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));",
151 gFM.c_str(), gF.c_str(), gF.c_str());
152 fragBuilder->codeAppendf("%s = %s.x*%s.x - %s.y*%s.z;",
153 func.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn());
154 fragBuilder->codeAppendf("%s = abs(%s);", func.c_str(), func.c_str());
155 fragBuilder->codeAppendf("%s = %s / %s;",
156 edgeAlpha.c_str(), func.c_str(), gFM.c_str());
157 fragBuilder->codeAppendf("%s = max(1.0 - %s, 0.0);",
158 edgeAlpha.c_str(), edgeAlpha.c_str());
159 // Add line below for smooth cubic ramp
160 // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);");
161 break;
162 }
163 case kFillAA_GrProcessorEdgeType: {
164 fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn());
165 fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn());
166 fragBuilder->codeAppendf("%s ="
167 "2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
168 dfdx.c_str(),
169 v.fsIn(), dklmdx.c_str(),
170 v.fsIn(), dklmdx.c_str(),
171 v.fsIn(), dklmdx.c_str());
172 fragBuilder->codeAppendf("%s ="
173 "2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
174 dfdy.c_str(),
175 v.fsIn(), dklmdy.c_str(),
176 v.fsIn(), dklmdy.c_str(),
177 v.fsIn(), dklmdy.c_str());
178 fragBuilder->codeAppendf("%s = vec2(%s, %s);", gF.c_str(), dfdx.c_str(), dfdy.c_str());
179 fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));",
180 gFM.c_str(), gF.c_str(), gF.c_str());
181 fragBuilder->codeAppendf("%s = %s.x * %s.x - %s.y * %s.z;",
182 func.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn());
183 fragBuilder->codeAppendf("%s = %s / %s;",
184 edgeAlpha.c_str(), func.c_str(), gFM.c_str());
185 fragBuilder->codeAppendf("%s = clamp(0.5 - %s, 0.0, 1.0);",
186 edgeAlpha.c_str(), edgeAlpha.c_str());
187 // Add line below for smooth cubic ramp
188 // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);");
189 break;
190 }
191 case kFillBW_GrProcessorEdgeType: {
192 fragBuilder->codeAppendf("%s = %s.x * %s.x - %s.y * %s.z;",
193 edgeAlpha.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn());
194 fragBuilder->codeAppendf("%s = float(%s < 0.0);",
195 edgeAlpha.c_str(), edgeAlpha.c_str());
196 break;
197 }
198 default:
199 SkFAIL("Shouldn't get here");
200 }
201
202 // TODO should we really be doing this?
203 if (gp.coverageScale() != 0xff) {
204 const char* coverageScale;
205 fCoverageScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
206 kFloat_GrSLType,
207 kHigh_GrSLPrecision,
208 "Coverage",
209 &coverageScale);
210 fragBuilder->codeAppendf("%s = vec4(%s * %s);",
211 args.fOutputCoverage, coverageScale, edgeAlpha.c_str());
212 } else {
213 fragBuilder->codeAppendf("%s = vec4(%s);", args.fOutputCoverage, edgeAlpha.c_str());
214 }
215 }
216
GenKey(const GrGeometryProcessor & gp,const GrShaderCaps &,GrProcessorKeyBuilder * b)217 void GrGLConicEffect::GenKey(const GrGeometryProcessor& gp,
218 const GrShaderCaps&,
219 GrProcessorKeyBuilder* b) {
220 const GrConicEffect& ce = gp.cast<GrConicEffect>();
221 uint32_t key = ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
222 key |= 0xff != ce.coverageScale() ? 0x8 : 0x0;
223 key |= ce.usesLocalCoords() && ce.localMatrix().hasPerspective() ? 0x10 : 0x0;
224 key |= ComputePosKey(ce.viewMatrix()) << 5;
225 b->add32(key);
226 }
227
228 //////////////////////////////////////////////////////////////////////////////
229
~GrConicEffect()230 GrConicEffect::~GrConicEffect() {}
231
getGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const232 void GrConicEffect::getGLSLProcessorKey(const GrShaderCaps& caps,
233 GrProcessorKeyBuilder* b) const {
234 GrGLConicEffect::GenKey(*this, caps, b);
235 }
236
createGLSLInstance(const GrShaderCaps &) const237 GrGLSLPrimitiveProcessor* GrConicEffect::createGLSLInstance(const GrShaderCaps&) const {
238 return new GrGLConicEffect(*this);
239 }
240
GrConicEffect(GrColor color,const SkMatrix & viewMatrix,uint8_t coverage,GrPrimitiveEdgeType edgeType,const SkMatrix & localMatrix,bool usesLocalCoords)241 GrConicEffect::GrConicEffect(GrColor color, const SkMatrix& viewMatrix, uint8_t coverage,
242 GrPrimitiveEdgeType edgeType, const SkMatrix& localMatrix,
243 bool usesLocalCoords)
244 : fColor(color)
245 , fViewMatrix(viewMatrix)
246 , fLocalMatrix(viewMatrix)
247 , fUsesLocalCoords(usesLocalCoords)
248 , fCoverageScale(coverage)
249 , fEdgeType(edgeType) {
250 this->initClassID<GrConicEffect>();
251 fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType,
252 kHigh_GrSLPrecision);
253 fInConicCoeffs = &this->addVertexAttrib("inConicCoeffs", kVec4f_GrVertexAttribType);
254 }
255
256 //////////////////////////////////////////////////////////////////////////////
257
258 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrConicEffect);
259
260 #if GR_TEST_UTILS
TestCreate(GrProcessorTestData * d)261 sk_sp<GrGeometryProcessor> GrConicEffect::TestCreate(GrProcessorTestData* d) {
262 sk_sp<GrGeometryProcessor> gp;
263 do {
264 GrPrimitiveEdgeType edgeType =
265 static_cast<GrPrimitiveEdgeType>(
266 d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt));
267 gp = GrConicEffect::Make(GrRandomColor(d->fRandom), GrTest::TestMatrix(d->fRandom),
268 edgeType, *d->caps(), GrTest::TestMatrix(d->fRandom),
269 d->fRandom->nextBool());
270 } while (nullptr == gp);
271 return gp;
272 }
273 #endif
274
275 //////////////////////////////////////////////////////////////////////////////
276 // Quad
277 //////////////////////////////////////////////////////////////////////////////
278
279 class GrGLQuadEffect : public GrGLSLGeometryProcessor {
280 public:
281 GrGLQuadEffect(const GrGeometryProcessor&);
282
283 void onEmitCode(EmitArgs&, GrGPArgs*) override;
284
285 static inline void GenKey(const GrGeometryProcessor&,
286 const GrShaderCaps&,
287 GrProcessorKeyBuilder*);
288
setData(const GrGLSLProgramDataManager & pdman,const GrPrimitiveProcessor & primProc,FPCoordTransformIter && transformIter)289 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc,
290 FPCoordTransformIter&& transformIter) override {
291 const GrQuadEffect& qe = primProc.cast<GrQuadEffect>();
292
293 if (!qe.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(qe.viewMatrix())) {
294 fViewMatrix = qe.viewMatrix();
295 float viewMatrix[3 * 3];
296 GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
297 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
298 }
299
300 if (qe.color() != fColor) {
301 float c[4];
302 GrColorToRGBAFloat(qe.color(), c);
303 pdman.set4fv(fColorUniform, 1, c);
304 fColor = qe.color();
305 }
306
307 if (qe.coverageScale() != 0xff && qe.coverageScale() != fCoverageScale) {
308 pdman.set1f(fCoverageScaleUniform, GrNormalizeByteToFloat(qe.coverageScale()));
309 fCoverageScale = qe.coverageScale();
310 }
311 this->setTransformDataHelper(qe.localMatrix(), pdman, &transformIter);
312 }
313
314 private:
315 SkMatrix fViewMatrix;
316 GrColor fColor;
317 uint8_t fCoverageScale;
318 GrPrimitiveEdgeType fEdgeType;
319 UniformHandle fColorUniform;
320 UniformHandle fCoverageScaleUniform;
321 UniformHandle fViewMatrixUniform;
322
323 typedef GrGLSLGeometryProcessor INHERITED;
324 };
325
GrGLQuadEffect(const GrGeometryProcessor & processor)326 GrGLQuadEffect::GrGLQuadEffect(const GrGeometryProcessor& processor)
327 : fViewMatrix(SkMatrix::InvalidMatrix()), fColor(GrColor_ILLEGAL), fCoverageScale(0xff) {
328 const GrQuadEffect& ce = processor.cast<GrQuadEffect>();
329 fEdgeType = ce.getEdgeType();
330 }
331
onEmitCode(EmitArgs & args,GrGPArgs * gpArgs)332 void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
333 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
334 const GrQuadEffect& gp = args.fGP.cast<GrQuadEffect>();
335 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
336 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
337
338 // emit attributes
339 varyingHandler->emitAttributes(gp);
340
341 GrGLSLVertToFrag v(kVec4f_GrSLType);
342 varyingHandler->addVarying("HairQuadEdge", &v);
343 vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inHairQuadEdge()->fName);
344
345 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
346 // Setup pass through color
347 this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform);
348
349 // Setup position
350 this->setupPosition(vertBuilder,
351 uniformHandler,
352 gpArgs,
353 gp.inPosition()->fName,
354 gp.viewMatrix(),
355 &fViewMatrixUniform);
356
357 // emit transforms with position
358 this->emitTransforms(vertBuilder,
359 varyingHandler,
360 uniformHandler,
361 gpArgs->fPositionVar,
362 gp.inPosition()->fName,
363 gp.localMatrix(),
364 args.fFPCoordTransformHandler);
365
366 fragBuilder->codeAppendf("float edgeAlpha;");
367
368 switch (fEdgeType) {
369 case kHairlineAA_GrProcessorEdgeType: {
370 fragBuilder->codeAppendf("vec2 duvdx = dFdx(%s.xy);", v.fsIn());
371 fragBuilder->codeAppendf("vec2 duvdy = dFdy(%s.xy);", v.fsIn());
372 fragBuilder->codeAppendf("vec2 gF = vec2(2.0 * %s.x * duvdx.x - duvdx.y,"
373 " 2.0 * %s.x * duvdy.x - duvdy.y);",
374 v.fsIn(), v.fsIn());
375 fragBuilder->codeAppendf("edgeAlpha = (%s.x * %s.x - %s.y);",
376 v.fsIn(), v.fsIn(), v.fsIn());
377 fragBuilder->codeAppend("edgeAlpha = sqrt(edgeAlpha * edgeAlpha / dot(gF, gF));");
378 fragBuilder->codeAppend("edgeAlpha = max(1.0 - edgeAlpha, 0.0);");
379 // Add line below for smooth cubic ramp
380 // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);");
381 break;
382 }
383 case kFillAA_GrProcessorEdgeType: {
384 fragBuilder->codeAppendf("vec2 duvdx = dFdx(%s.xy);", v.fsIn());
385 fragBuilder->codeAppendf("vec2 duvdy = dFdy(%s.xy);", v.fsIn());
386 fragBuilder->codeAppendf("vec2 gF = vec2(2.0 * %s.x * duvdx.x - duvdx.y,"
387 " 2.0 * %s.x * duvdy.x - duvdy.y);",
388 v.fsIn(), v.fsIn());
389 fragBuilder->codeAppendf("edgeAlpha = (%s.x * %s.x - %s.y);",
390 v.fsIn(), v.fsIn(), v.fsIn());
391 fragBuilder->codeAppend("edgeAlpha = edgeAlpha / sqrt(dot(gF, gF));");
392 fragBuilder->codeAppend("edgeAlpha = clamp(0.5 - edgeAlpha, 0.0, 1.0);");
393 // Add line below for smooth cubic ramp
394 // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);");
395 break;
396 }
397 case kFillBW_GrProcessorEdgeType: {
398 fragBuilder->codeAppendf("edgeAlpha = (%s.x * %s.x - %s.y);",
399 v.fsIn(), v.fsIn(), v.fsIn());
400 fragBuilder->codeAppend("edgeAlpha = float(edgeAlpha < 0.0);");
401 break;
402 }
403 default:
404 SkFAIL("Shouldn't get here");
405 }
406
407 if (0xff != gp.coverageScale()) {
408 const char* coverageScale;
409 fCoverageScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
410 kFloat_GrSLType,
411 kDefault_GrSLPrecision,
412 "Coverage",
413 &coverageScale);
414 fragBuilder->codeAppendf("%s = vec4(%s * edgeAlpha);", args.fOutputCoverage, coverageScale);
415 } else {
416 fragBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCoverage);
417 }
418 }
419
GenKey(const GrGeometryProcessor & gp,const GrShaderCaps &,GrProcessorKeyBuilder * b)420 void GrGLQuadEffect::GenKey(const GrGeometryProcessor& gp,
421 const GrShaderCaps&,
422 GrProcessorKeyBuilder* b) {
423 const GrQuadEffect& ce = gp.cast<GrQuadEffect>();
424 uint32_t key = ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
425 key |= ce.coverageScale() != 0xff ? 0x8 : 0x0;
426 key |= ce.usesLocalCoords() && ce.localMatrix().hasPerspective() ? 0x10 : 0x0;
427 key |= ComputePosKey(ce.viewMatrix()) << 5;
428 b->add32(key);
429 }
430
431 //////////////////////////////////////////////////////////////////////////////
432
~GrQuadEffect()433 GrQuadEffect::~GrQuadEffect() {}
434
getGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const435 void GrQuadEffect::getGLSLProcessorKey(const GrShaderCaps& caps,
436 GrProcessorKeyBuilder* b) const {
437 GrGLQuadEffect::GenKey(*this, caps, b);
438 }
439
createGLSLInstance(const GrShaderCaps &) const440 GrGLSLPrimitiveProcessor* GrQuadEffect::createGLSLInstance(const GrShaderCaps&) const {
441 return new GrGLQuadEffect(*this);
442 }
443
GrQuadEffect(GrColor color,const SkMatrix & viewMatrix,uint8_t coverage,GrPrimitiveEdgeType edgeType,const SkMatrix & localMatrix,bool usesLocalCoords)444 GrQuadEffect::GrQuadEffect(GrColor color, const SkMatrix& viewMatrix, uint8_t coverage,
445 GrPrimitiveEdgeType edgeType, const SkMatrix& localMatrix,
446 bool usesLocalCoords)
447 : fColor(color)
448 , fViewMatrix(viewMatrix)
449 , fLocalMatrix(localMatrix)
450 , fUsesLocalCoords(usesLocalCoords)
451 , fCoverageScale(coverage)
452 , fEdgeType(edgeType) {
453 this->initClassID<GrQuadEffect>();
454 fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType,
455 kHigh_GrSLPrecision);
456 fInHairQuadEdge = &this->addVertexAttrib("inHairQuadEdge", kVec4f_GrVertexAttribType);
457 }
458
459 //////////////////////////////////////////////////////////////////////////////
460
461 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrQuadEffect);
462
463 #if GR_TEST_UTILS
TestCreate(GrProcessorTestData * d)464 sk_sp<GrGeometryProcessor> GrQuadEffect::TestCreate(GrProcessorTestData* d) {
465 sk_sp<GrGeometryProcessor> gp;
466 do {
467 GrPrimitiveEdgeType edgeType = static_cast<GrPrimitiveEdgeType>(
468 d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt));
469 gp = GrQuadEffect::Make(GrRandomColor(d->fRandom), GrTest::TestMatrix(d->fRandom), edgeType,
470 *d->caps(), GrTest::TestMatrix(d->fRandom),
471 d->fRandom->nextBool());
472 } while (nullptr == gp);
473 return gp;
474 }
475 #endif
476
477 //////////////////////////////////////////////////////////////////////////////
478 // Cubic
479 //////////////////////////////////////////////////////////////////////////////
480
481 class GrGLCubicEffect : public GrGLSLGeometryProcessor {
482 public:
483 GrGLCubicEffect(const GrGeometryProcessor&);
484
485 void onEmitCode(EmitArgs&, GrGPArgs*) override;
486
487 static inline void GenKey(const GrGeometryProcessor&,
488 const GrShaderCaps&,
489 GrProcessorKeyBuilder*);
490
setData(const GrGLSLProgramDataManager & pdman,const GrPrimitiveProcessor & primProc,FPCoordTransformIter && transformIter)491 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc,
492 FPCoordTransformIter&& transformIter) override {
493 const GrCubicEffect& ce = primProc.cast<GrCubicEffect>();
494
495 if (!ce.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(ce.viewMatrix())) {
496 fViewMatrix = ce.viewMatrix();
497 float viewMatrix[3 * 3];
498 GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
499 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
500 }
501
502 if (ce.color() != fColor) {
503 float c[4];
504 GrColorToRGBAFloat(ce.color(), c);
505 pdman.set4fv(fColorUniform, 1, c);
506 fColor = ce.color();
507 }
508 this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
509 }
510
511 private:
512 SkMatrix fViewMatrix;
513 GrColor fColor;
514 GrPrimitiveEdgeType fEdgeType;
515 UniformHandle fColorUniform;
516 UniformHandle fViewMatrixUniform;
517
518 typedef GrGLSLGeometryProcessor INHERITED;
519 };
520
GrGLCubicEffect(const GrGeometryProcessor & processor)521 GrGLCubicEffect::GrGLCubicEffect(const GrGeometryProcessor& processor)
522 : fViewMatrix(SkMatrix::InvalidMatrix()), fColor(GrColor_ILLEGAL) {
523 const GrCubicEffect& ce = processor.cast<GrCubicEffect>();
524 fEdgeType = ce.getEdgeType();
525 }
526
onEmitCode(EmitArgs & args,GrGPArgs * gpArgs)527 void GrGLCubicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
528 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
529 const GrCubicEffect& gp = args.fGP.cast<GrCubicEffect>();
530 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
531 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
532
533 // emit attributes
534 varyingHandler->emitAttributes(gp);
535
536 GrGLSLVertToFrag v(kVec4f_GrSLType);
537 varyingHandler->addVarying("CubicCoeffs", &v, kHigh_GrSLPrecision);
538 vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inCubicCoeffs()->fName);
539
540 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
541 // Setup pass through color
542 if (!gp.colorIgnored()) {
543 this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform);
544 }
545
546 // Setup position
547 this->setupPosition(vertBuilder,
548 uniformHandler,
549 gpArgs,
550 gp.inPosition()->fName,
551 gp.viewMatrix(),
552 &fViewMatrixUniform);
553
554 // emit transforms with position
555 this->emitTransforms(vertBuilder,
556 varyingHandler,
557 uniformHandler,
558 gpArgs->fPositionVar,
559 gp.inPosition()->fName,
560 args.fFPCoordTransformHandler);
561
562
563 GrShaderVar edgeAlpha("edgeAlpha", kFloat_GrSLType, 0, kHigh_GrSLPrecision);
564 GrShaderVar dklmdx("dklmdx", kVec3f_GrSLType, 0, kHigh_GrSLPrecision);
565 GrShaderVar dklmdy("dklmdy", kVec3f_GrSLType, 0, kHigh_GrSLPrecision);
566 GrShaderVar dfdx("dfdx", kFloat_GrSLType, 0, kHigh_GrSLPrecision);
567 GrShaderVar dfdy("dfdy", kFloat_GrSLType, 0, kHigh_GrSLPrecision);
568 GrShaderVar gF("gF", kVec2f_GrSLType, 0, kHigh_GrSLPrecision);
569 GrShaderVar gFM("gFM", kFloat_GrSLType, 0, kHigh_GrSLPrecision);
570 GrShaderVar func("func", kFloat_GrSLType, 0, kHigh_GrSLPrecision);
571
572 fragBuilder->declAppend(edgeAlpha);
573 fragBuilder->declAppend(dklmdx);
574 fragBuilder->declAppend(dklmdy);
575 fragBuilder->declAppend(dfdx);
576 fragBuilder->declAppend(dfdy);
577 fragBuilder->declAppend(gF);
578 fragBuilder->declAppend(gFM);
579 fragBuilder->declAppend(func);
580
581 switch (fEdgeType) {
582 case kHairlineAA_GrProcessorEdgeType: {
583 fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn());
584 fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn());
585 fragBuilder->codeAppendf("%s = 3.0 * %s.x * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
586 dfdx.c_str(), v.fsIn(), v.fsIn(), dklmdx.c_str(), v.fsIn(),
587 dklmdx.c_str(), v.fsIn(), dklmdx.c_str());
588 fragBuilder->codeAppendf("%s = 3.0 * %s.x * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
589 dfdy.c_str(), v.fsIn(), v.fsIn(), dklmdy.c_str(), v.fsIn(),
590 dklmdy.c_str(), v.fsIn(), dklmdy.c_str());
591 fragBuilder->codeAppendf("%s = vec2(%s, %s);", gF.c_str(), dfdx.c_str(), dfdy.c_str());
592 fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));",
593 gFM.c_str(), gF.c_str(), gF.c_str());
594 fragBuilder->codeAppendf("%s = %s.x * %s.x * %s.x - %s.y * %s.z;",
595 func.c_str(), v.fsIn(), v.fsIn(),
596 v.fsIn(), v.fsIn(), v.fsIn());
597 fragBuilder->codeAppendf("%s = abs(%s);", func.c_str(), func.c_str());
598 fragBuilder->codeAppendf("%s = %s / %s;",
599 edgeAlpha.c_str(), func.c_str(), gFM.c_str());
600 fragBuilder->codeAppendf("%s = max(1.0 - %s, 0.0);",
601 edgeAlpha.c_str(), edgeAlpha.c_str());
602 // Add line below for smooth cubic ramp
603 // fragBuilder->codeAppendf("%s = %s * %s * (3.0 - 2.0 * %s);",
604 // edgeAlpha.c_str(), edgeAlpha.c_str(), edgeAlpha.c_str(),
605 // edgeAlpha.c_str());
606 break;
607 }
608 case kFillAA_GrProcessorEdgeType: {
609 fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn());
610 fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn());
611 fragBuilder->codeAppendf("%s ="
612 "3.0 * %s.x * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
613 dfdx.c_str(), v.fsIn(), v.fsIn(), dklmdx.c_str(), v.fsIn(),
614 dklmdx.c_str(), v.fsIn(), dklmdx.c_str());
615 fragBuilder->codeAppendf("%s = 3.0 * %s.x * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
616 dfdy.c_str(), v.fsIn(), v.fsIn(), dklmdy.c_str(), v.fsIn(),
617 dklmdy.c_str(), v.fsIn(), dklmdy.c_str());
618 fragBuilder->codeAppendf("%s = vec2(%s, %s);", gF.c_str(), dfdx.c_str(), dfdy.c_str());
619 fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));",
620 gFM.c_str(), gF.c_str(), gF.c_str());
621 fragBuilder->codeAppendf("%s = %s.x * %s.x * %s.x - %s.y * %s.z;",
622 func.c_str(),
623 v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn());
624 fragBuilder->codeAppendf("%s = %s / %s;",
625 edgeAlpha.c_str(), func.c_str(), gFM.c_str());
626 fragBuilder->codeAppendf("%s = clamp(0.5 - %s, 0.0, 1.0);",
627 edgeAlpha.c_str(), edgeAlpha.c_str());
628 // Add line below for smooth cubic ramp
629 // fragBuilder->codeAppendf("%s = %s * %s * (3.0 - 2.0 * %s);",
630 // edgeAlpha.c_str(), edgeAlpha.c_str(), edgeAlpha.c_str(),
631 // edgeAlpha.c_str());
632 break;
633 }
634 case kFillBW_GrProcessorEdgeType: {
635 fragBuilder->codeAppendf("%s = %s.x * %s.x * %s.x - %s.y * %s.z;",
636 edgeAlpha.c_str(), v.fsIn(), v.fsIn(),
637 v.fsIn(), v.fsIn(), v.fsIn());
638 fragBuilder->codeAppendf("%s = float(%s < 0.0);", edgeAlpha.c_str(), edgeAlpha.c_str());
639 break;
640 }
641 default:
642 SkFAIL("Shouldn't get here");
643 }
644
645
646 fragBuilder->codeAppendf("%s = vec4(%s);", args.fOutputCoverage, edgeAlpha.c_str());
647 }
648
GenKey(const GrGeometryProcessor & gp,const GrShaderCaps &,GrProcessorKeyBuilder * b)649 void GrGLCubicEffect::GenKey(const GrGeometryProcessor& gp,
650 const GrShaderCaps&,
651 GrProcessorKeyBuilder* b) {
652 const GrCubicEffect& ce = gp.cast<GrCubicEffect>();
653 uint32_t key = ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
654 key |= ComputePosKey(ce.viewMatrix()) << 5;
655 b->add32(key);
656 }
657
658 //////////////////////////////////////////////////////////////////////////////
659
~GrCubicEffect()660 GrCubicEffect::~GrCubicEffect() {}
661
getGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const662 void GrCubicEffect::getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
663 GrGLCubicEffect::GenKey(*this, caps, b);
664 }
665
createGLSLInstance(const GrShaderCaps &) const666 GrGLSLPrimitiveProcessor* GrCubicEffect::createGLSLInstance(const GrShaderCaps&) const {
667 return new GrGLCubicEffect(*this);
668 }
669
GrCubicEffect(GrColor color,const SkMatrix & viewMatrix,GrPrimitiveEdgeType edgeType)670 GrCubicEffect::GrCubicEffect(GrColor color, const SkMatrix& viewMatrix,
671 GrPrimitiveEdgeType edgeType)
672 : fColor(color)
673 , fViewMatrix(viewMatrix)
674 , fEdgeType(edgeType) {
675 this->initClassID<GrCubicEffect>();
676 fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType,
677 kHigh_GrSLPrecision);
678 fInCubicCoeffs = &this->addVertexAttrib("inCubicCoeffs", kVec4f_GrVertexAttribType);
679 }
680
681 //////////////////////////////////////////////////////////////////////////////
682
683 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrCubicEffect);
684
685 #if GR_TEST_UTILS
TestCreate(GrProcessorTestData * d)686 sk_sp<GrGeometryProcessor> GrCubicEffect::TestCreate(GrProcessorTestData* d) {
687 sk_sp<GrGeometryProcessor> gp;
688 do {
689 GrPrimitiveEdgeType edgeType =
690 static_cast<GrPrimitiveEdgeType>(
691 d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt));
692 gp = GrCubicEffect::Make(GrRandomColor(d->fRandom), GrTest::TestMatrix(d->fRandom),
693 edgeType, *d->caps());
694 } while (nullptr == gp);
695 return gp;
696 }
697 #endif
698