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 "src/gpu/GrShaderCaps.h"
9#include "src/gpu/effects/GrBezierEffect.h"
10#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
11#include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
12#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
13#include "src/gpu/glsl/GrGLSLUniformHandler.h"
14#include "src/gpu/glsl/GrGLSLVarying.h"
15#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
16
17class GrGLConicEffect : public GrGLSLGeometryProcessor {
18public:
19 GrGLConicEffect(const GrGeometryProcessor&);
20
21 void onEmitCode(EmitArgs&, GrGPArgs*) override;
22
23 static inline void GenKey(const GrGeometryProcessor&,
24 const GrShaderCaps&,
25 GrProcessorKeyBuilder*);
26
27 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc,
28 const CoordTransformRange& transformRange) override {
29 const GrConicEffect& ce = primProc.cast<GrConicEffect>();
30
31 if (!ce.viewMatrix().isIdentity() &&
32 !SkMatrixPriv::CheapEqual(fViewMatrix, ce.viewMatrix()))
33 {
34 fViewMatrix = ce.viewMatrix();
35 pdman.setSkMatrix(fViewMatrixUniform, fViewMatrix);
36 }
37
38 if (ce.color() != fColor) {
39 pdman.set4fv(fColorUniform, 1, ce.color().vec());
40 fColor = ce.color();
41 }
42
43 if (ce.coverageScale() != 0xff && ce.coverageScale() != fCoverageScale) {
44 pdman.set1f(fCoverageScaleUniform, GrNormalizeByteToFloat(ce.coverageScale()));
45 fCoverageScale = ce.coverageScale();
46 }
47 this->setTransformDataHelper(ce.localMatrix(), pdman, transformRange);
48 }
49
50private:
51 SkMatrix fViewMatrix;
52 SkPMColor4f fColor;
53 uint8_t fCoverageScale;
54 GrClipEdgeType fEdgeType;
55 UniformHandle fColorUniform;
56 UniformHandle fCoverageScaleUniform;
57 UniformHandle fViewMatrixUniform;
58
59 typedef GrGLSLGeometryProcessor INHERITED;
60};
61
62GrGLConicEffect::GrGLConicEffect(const GrGeometryProcessor& processor)
63 : fViewMatrix(SkMatrix::InvalidMatrix()), fColor(SK_PMColor4fILLEGAL), fCoverageScale(0xff) {
64 const GrConicEffect& ce = processor.cast<GrConicEffect>();
65 fEdgeType = ce.getEdgeType();
66}
67
68void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
69 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
70 const GrConicEffect& gp = args.fGP.cast<GrConicEffect>();
71 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
72 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
73
74 // emit attributes
75 varyingHandler->emitAttributes(gp);
76
77 GrGLSLVarying v(kFloat4_GrSLType);
78 varyingHandler->addVarying("ConicCoeffs", &v);
79 vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inConicCoeffs().name());
80
81 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
82 // Setup pass through color
83 this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform);
84
85 // Setup position
86 this->writeOutputPosition(vertBuilder,
87 uniformHandler,
88 gpArgs,
89 gp.inPosition().name(),
90 gp.viewMatrix(),
91 &fViewMatrixUniform);
92
93 // emit transforms with position
94 this->emitTransforms(vertBuilder,
95 varyingHandler,
96 uniformHandler,
97 gp.inPosition().asShaderVar(),
98 gp.localMatrix(),
99 args.fFPCoordTransformHandler);
100
101 // TODO: we should check on the number of bits float and half provide and use the smallest one
102 // that suffices. Additionally we should assert that the upstream code only lets us get here if
103 // either float or half provides the required number of bits.
104
105 GrShaderVar edgeAlpha("edgeAlpha", kHalf_GrSLType, 0);
106 GrShaderVar dklmdx("dklmdx", kFloat3_GrSLType, 0);
107 GrShaderVar dklmdy("dklmdy", kFloat3_GrSLType, 0);
108 GrShaderVar dfdx("dfdx", kFloat_GrSLType, 0);
109 GrShaderVar dfdy("dfdy", kFloat_GrSLType, 0);
110 GrShaderVar gF("gF", kFloat2_GrSLType, 0);
111 GrShaderVar gFM("gFM", kFloat_GrSLType, 0);
112 GrShaderVar func("func", kFloat_GrSLType, 0);
113
114 fragBuilder->declAppend(edgeAlpha);
115 fragBuilder->declAppend(dklmdx);
116 fragBuilder->declAppend(dklmdy);
117 fragBuilder->declAppend(dfdx);
118 fragBuilder->declAppend(dfdy);
119 fragBuilder->declAppend(gF);
120 fragBuilder->declAppend(gFM);
121 fragBuilder->declAppend(func);
122
123 switch (fEdgeType) {
124 case GrClipEdgeType::kHairlineAA: {
125 fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn());
126 fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn());
127 fragBuilder->codeAppendf("%s = 2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
128 dfdx.c_str(),
129 v.fsIn(), dklmdx.c_str(),
130 v.fsIn(), dklmdx.c_str(),
131 v.fsIn(), dklmdx.c_str());
132 fragBuilder->codeAppendf("%s = 2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
133 dfdy.c_str(),
134 v.fsIn(), dklmdy.c_str(),
135 v.fsIn(), dklmdy.c_str(),
136 v.fsIn(), dklmdy.c_str());
137 fragBuilder->codeAppendf("%s = float2(%s, %s);", gF.c_str(), dfdx.c_str(),
138 dfdy.c_str());
139 fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));",
140 gFM.c_str(), gF.c_str(), gF.c_str());
141 fragBuilder->codeAppendf("%s = %s.x*%s.x - %s.y*%s.z;",
142 func.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn());
143 fragBuilder->codeAppendf("%s = abs(%s);", func.c_str(), func.c_str());
144 fragBuilder->codeAppendf("%s = half(%s / %s);",
145 edgeAlpha.c_str(), func.c_str(), gFM.c_str());
146 fragBuilder->codeAppendf("%s = max(1.0 - %s, 0.0);",
147 edgeAlpha.c_str(), edgeAlpha.c_str());
148 // Add line below for smooth cubic ramp
149 // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);");
150 break;
151 }
152 case GrClipEdgeType::kFillAA: {
153 fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn());
154 fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn());
155 fragBuilder->codeAppendf("%s ="
156 "2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
157 dfdx.c_str(),
158 v.fsIn(), dklmdx.c_str(),
159 v.fsIn(), dklmdx.c_str(),
160 v.fsIn(), dklmdx.c_str());
161 fragBuilder->codeAppendf("%s ="
162 "2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
163 dfdy.c_str(),
164 v.fsIn(), dklmdy.c_str(),
165 v.fsIn(), dklmdy.c_str(),
166 v.fsIn(), dklmdy.c_str());
167 fragBuilder->codeAppendf("%s = float2(%s, %s);", gF.c_str(), dfdx.c_str(),
168 dfdy.c_str());
169 fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));",
170 gFM.c_str(), gF.c_str(), gF.c_str());
171 fragBuilder->codeAppendf("%s = %s.x * %s.x - %s.y * %s.z;",
172 func.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn());
173 fragBuilder->codeAppendf("%s = half(%s / %s);",
174 edgeAlpha.c_str(), func.c_str(), gFM.c_str());
175 fragBuilder->codeAppendf("%s = saturate(0.5 - %s);",
176 edgeAlpha.c_str(), edgeAlpha.c_str());
177 // Add line below for smooth cubic ramp
178 // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);");
179 break;
180 }
181 case GrClipEdgeType::kFillBW: {
182 fragBuilder->codeAppendf("%s = half(%s.x * %s.x - %s.y * %s.z);",
183 edgeAlpha.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn());
184 fragBuilder->codeAppendf("%s = half(%s < 0.0);",
185 edgeAlpha.c_str(), edgeAlpha.c_str());
186 break;
187 }
188 default:
189 SK_ABORT("Shouldn't get here");
190 }
191
192 // TODO should we really be doing this?
193 if (gp.coverageScale() != 0xff) {
194 const char* coverageScale;
195 fCoverageScaleUniform = uniformHandler->addUniform(nullptr,
196 kFragment_GrShaderFlag,
197 kFloat_GrSLType,
198 "Coverage",
199 &coverageScale);
200 fragBuilder->codeAppendf("%s = half4(half(%s) * %s);",
201 args.fOutputCoverage, coverageScale, edgeAlpha.c_str());
202 } else {
203 fragBuilder->codeAppendf("%s = half4(%s);", args.fOutputCoverage, edgeAlpha.c_str());
204 }
205}
206
207void GrGLConicEffect::GenKey(const GrGeometryProcessor& gp,
208 const GrShaderCaps&,
209 GrProcessorKeyBuilder* b) {
210 const GrConicEffect& ce = gp.cast<GrConicEffect>();
211 uint32_t key = ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
212 key |= 0xff != ce.coverageScale() ? 0x8 : 0x0;
213 key |= ce.usesLocalCoords() && ce.localMatrix().hasPerspective() ? 0x10 : 0x0;
214 key |= ComputePosKey(ce.viewMatrix()) << 5;
215 b->add32(key);
216}
217
218//////////////////////////////////////////////////////////////////////////////
219
220constexpr GrPrimitiveProcessor::Attribute GrConicEffect::kAttributes[];
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(const SkPMColor4f& 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 this->setVertexAttributes(kAttributes, SK_ARRAY_COUNT(kAttributes));
244}
245
246//////////////////////////////////////////////////////////////////////////////
247
248GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrConicEffect);
249
250#if GR_TEST_UTILS
251GrGeometryProcessor* GrConicEffect::TestCreate(GrProcessorTestData* d) {
252 GrGeometryProcessor* gp;
253 do {
254 GrClipEdgeType edgeType =
255 static_cast<GrClipEdgeType>(
256 d->fRandom->nextULessThan(kGrClipEdgeTypeCnt));
257 gp = GrConicEffect::Make(d->allocator(),
258 SkPMColor4f::FromBytes_RGBA(GrRandomColor(d->fRandom)),
259 GrTest::TestMatrix(d->fRandom), edgeType, *d->caps(),
260 GrTest::TestMatrix(d->fRandom), 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 const CoordTransformRange& transformRange) override {
282 const GrQuadEffect& qe = primProc.cast<GrQuadEffect>();
283
284 if (!qe.viewMatrix().isIdentity() &&
285 !SkMatrixPriv::CheapEqual(fViewMatrix, qe.viewMatrix()))
286 {
287 fViewMatrix = qe.viewMatrix();
288 pdman.setSkMatrix(fViewMatrixUniform, fViewMatrix);
289 }
290
291 if (qe.color() != fColor) {
292 pdman.set4fv(fColorUniform, 1, qe.color().vec());
293 fColor = qe.color();
294 }
295
296 if (qe.coverageScale() != 0xff && qe.coverageScale() != fCoverageScale) {
297 pdman.set1f(fCoverageScaleUniform, GrNormalizeByteToFloat(qe.coverageScale()));
298 fCoverageScale = qe.coverageScale();
299 }
300 this->setTransformDataHelper(qe.localMatrix(), pdman, transformRange);
301 }
302
303private:
304 SkMatrix fViewMatrix;
305 SkPMColor4f fColor;
306 uint8_t fCoverageScale;
307 GrClipEdgeType fEdgeType;
308 UniformHandle fColorUniform;
309 UniformHandle fCoverageScaleUniform;
310 UniformHandle fViewMatrixUniform;
311
312 typedef GrGLSLGeometryProcessor INHERITED;
313};
314
315GrGLQuadEffect::GrGLQuadEffect(const GrGeometryProcessor& processor)
316 : fViewMatrix(SkMatrix::InvalidMatrix()), fColor(SK_PMColor4fILLEGAL), fCoverageScale(0xff) {
317 const GrQuadEffect& ce = processor.cast<GrQuadEffect>();
318 fEdgeType = ce.getEdgeType();
319}
320
321void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
322 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
323 const GrQuadEffect& gp = args.fGP.cast<GrQuadEffect>();
324 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
325 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
326
327 // emit attributes
328 varyingHandler->emitAttributes(gp);
329
330 GrGLSLVarying v(kHalf4_GrSLType);
331 varyingHandler->addVarying("HairQuadEdge", &v);
332 vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inHairQuadEdge().name());
333
334 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
335 // Setup pass through color
336 this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform);
337
338 // Setup position
339 this->writeOutputPosition(vertBuilder,
340 uniformHandler,
341 gpArgs,
342 gp.inPosition().name(),
343 gp.viewMatrix(),
344 &fViewMatrixUniform);
345
346 // emit transforms with position
347 this->emitTransforms(vertBuilder,
348 varyingHandler,
349 uniformHandler,
350 gp.inPosition().asShaderVar(),
351 gp.localMatrix(),
352 args.fFPCoordTransformHandler);
353
354 fragBuilder->codeAppendf("half edgeAlpha;");
355
356 switch (fEdgeType) {
357 case GrClipEdgeType::kHairlineAA: {
358 fragBuilder->codeAppendf("half2 duvdx = half2(dFdx(%s.xy));", v.fsIn());
359 fragBuilder->codeAppendf("half2 duvdy = half2(dFdy(%s.xy));", v.fsIn());
360 fragBuilder->codeAppendf("half2 gF = half2(2.0 * %s.x * duvdx.x - duvdx.y,"
361 " 2.0 * %s.x * duvdy.x - duvdy.y);",
362 v.fsIn(), v.fsIn());
363 fragBuilder->codeAppendf("edgeAlpha = half(%s.x * %s.x - %s.y);",
364 v.fsIn(), v.fsIn(), v.fsIn());
365 fragBuilder->codeAppend("edgeAlpha = sqrt(edgeAlpha * edgeAlpha / dot(gF, gF));");
366 fragBuilder->codeAppend("edgeAlpha = max(1.0 - edgeAlpha, 0.0);");
367 // Add line below for smooth cubic ramp
368 // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);");
369 break;
370 }
371 case GrClipEdgeType::kFillAA: {
372 fragBuilder->codeAppendf("half2 duvdx = half2(dFdx(%s.xy));", v.fsIn());
373 fragBuilder->codeAppendf("half2 duvdy = half2(dFdy(%s.xy));", v.fsIn());
374 fragBuilder->codeAppendf("half2 gF = half2(2.0 * %s.x * duvdx.x - duvdx.y,"
375 " 2.0 * %s.x * duvdy.x - duvdy.y);",
376 v.fsIn(), v.fsIn());
377 fragBuilder->codeAppendf("edgeAlpha = half(%s.x * %s.x - %s.y);",
378 v.fsIn(), v.fsIn(), v.fsIn());
379 fragBuilder->codeAppend("edgeAlpha = edgeAlpha / sqrt(dot(gF, gF));");
380 fragBuilder->codeAppend("edgeAlpha = saturate(0.5 - edgeAlpha);");
381 // Add line below for smooth cubic ramp
382 // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);");
383 break;
384 }
385 case GrClipEdgeType::kFillBW: {
386 fragBuilder->codeAppendf("edgeAlpha = half(%s.x * %s.x - %s.y);",
387 v.fsIn(), v.fsIn(), v.fsIn());
388 fragBuilder->codeAppend("edgeAlpha = half(edgeAlpha < 0.0);");
389 break;
390 }
391 default:
392 SK_ABORT("Shouldn't get here");
393 }
394
395 if (0xff != gp.coverageScale()) {
396 const char* coverageScale;
397 fCoverageScaleUniform = uniformHandler->addUniform(nullptr,
398 kFragment_GrShaderFlag,
399 kHalf_GrSLType,
400 "Coverage",
401 &coverageScale);
402 fragBuilder->codeAppendf("%s = half4(%s * edgeAlpha);", args.fOutputCoverage,
403 coverageScale);
404 } else {
405 fragBuilder->codeAppendf("%s = half4(edgeAlpha);", args.fOutputCoverage);
406 }
407}
408
409void GrGLQuadEffect::GenKey(const GrGeometryProcessor& gp,
410 const GrShaderCaps&,
411 GrProcessorKeyBuilder* b) {
412 const GrQuadEffect& ce = gp.cast<GrQuadEffect>();
413 uint32_t key = ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
414 key |= ce.coverageScale() != 0xff ? 0x8 : 0x0;
415 key |= ce.usesLocalCoords() && ce.localMatrix().hasPerspective() ? 0x10 : 0x0;
416 key |= ComputePosKey(ce.viewMatrix()) << 5;
417 b->add32(key);
418}
419
420//////////////////////////////////////////////////////////////////////////////
421
422constexpr GrPrimitiveProcessor::Attribute GrQuadEffect::kAttributes[];
423
424GrQuadEffect::~GrQuadEffect() {}
425
426void GrQuadEffect::getGLSLProcessorKey(const GrShaderCaps& caps,
427 GrProcessorKeyBuilder* b) const {
428 GrGLQuadEffect::GenKey(*this, caps, b);
429}
430
431GrGLSLPrimitiveProcessor* GrQuadEffect::createGLSLInstance(const GrShaderCaps&) const {
432 return new GrGLQuadEffect(*this);
433}
434
435GrQuadEffect::GrQuadEffect(const SkPMColor4f& color, const SkMatrix& viewMatrix, uint8_t coverage,
436 GrClipEdgeType edgeType, const SkMatrix& localMatrix,
437 bool usesLocalCoords)
438 : INHERITED(kGrQuadEffect_ClassID)
439 , fColor(color)
440 , fViewMatrix(viewMatrix)
441 , fLocalMatrix(localMatrix)
442 , fUsesLocalCoords(usesLocalCoords)
443 , fCoverageScale(coverage)
444 , fEdgeType(edgeType) {
445 this->setVertexAttributes(kAttributes, SK_ARRAY_COUNT(kAttributes));
446}
447
448//////////////////////////////////////////////////////////////////////////////
449
450GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrQuadEffect);
451
452#if GR_TEST_UTILS
453GrGeometryProcessor* GrQuadEffect::TestCreate(GrProcessorTestData* d) {
454 GrGeometryProcessor* gp;
455 do {
456 GrClipEdgeType edgeType = static_cast<GrClipEdgeType>(
457 d->fRandom->nextULessThan(kGrClipEdgeTypeCnt));
458 gp = GrQuadEffect::Make(d->allocator(),
459 SkPMColor4f::FromBytes_RGBA(GrRandomColor(d->fRandom)),
460 GrTest::TestMatrix(d->fRandom), edgeType, *d->caps(),
461 GrTest::TestMatrix(d->fRandom), d->fRandom->nextBool());
462 } while (nullptr == gp);
463 return gp;
464}
465#endif
466