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