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