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