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