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,
28 const GrPrimitiveProcessor& primProc) override {
29 const GrConicEffect& ce = primProc.cast<GrConicEffect>();
30
31 this->setTransform(pdman, fViewMatrixUniform, ce.viewMatrix(), &fViewMatrix);
32 this->setTransform(pdman, fLocalMatrixUniform, ce.localMatrix(), &fLocalMatrix);
33
34 if (ce.color() != fColor) {
35 pdman.set4fv(fColorUniform, 1, ce.color().vec());
36 fColor = ce.color();
37 }
38
39 if (ce.coverageScale() != 0xff && ce.coverageScale() != fCoverageScale) {
40 pdman.set1f(fCoverageScaleUniform, GrNormalizeByteToFloat(ce.coverageScale()));
41 fCoverageScale = ce.coverageScale();
42 }
43 }
44
45private:
46 SkMatrix fViewMatrix;
47 SkMatrix fLocalMatrix;
48 SkPMColor4f fColor;
49 uint8_t fCoverageScale;
50 UniformHandle fColorUniform;
51 UniformHandle fCoverageScaleUniform;
52 UniformHandle fViewMatrixUniform;
53 UniformHandle fLocalMatrixUniform;
54
55 typedef GrGLSLGeometryProcessor INHERITED;
56};
57
58GrGLConicEffect::GrGLConicEffect(const GrGeometryProcessor& processor)
59 : fViewMatrix(SkMatrix::InvalidMatrix())
60 , fLocalMatrix(SkMatrix::InvalidMatrix())
61 , fColor(SK_PMColor4fILLEGAL)
62 , fCoverageScale(0xff) {}
63
64void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
65 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
66 const GrConicEffect& gp = args.fGP.cast<GrConicEffect>();
67 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
68 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
69
70 // emit attributes
71 varyingHandler->emitAttributes(gp);
72
73 GrGLSLVarying v(kFloat4_GrSLType);
74 varyingHandler->addVarying("ConicCoeffs", &v);
75 vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inConicCoeffs().name());
76
77 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
78 // Setup pass through color
79 this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform);
80
81 // Setup position
82 this->writeOutputPosition(vertBuilder,
83 uniformHandler,
84 gpArgs,
85 gp.inPosition().name(),
86 gp.viewMatrix(),
87 &fViewMatrixUniform);
88 if (gp.usesLocalCoords()) {
89 this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, gp.inPosition().asShaderVar(),
90 gp.localMatrix(), &fLocalMatrixUniform);
91 }
92
93 // TODO: we should check on the number of bits float and half provide and use the smallest one
94 // that suffices. Additionally we should assert that the upstream code only lets us get here if
95 // either float or half provides the required number of bits.
96
97 GrShaderVar edgeAlpha("edgeAlpha", kHalf_GrSLType, 0);
98 GrShaderVar dklmdx("dklmdx", kFloat3_GrSLType, 0);
99 GrShaderVar dklmdy("dklmdy", kFloat3_GrSLType, 0);
100 GrShaderVar dfdx("dfdx", kFloat_GrSLType, 0);
101 GrShaderVar dfdy("dfdy", kFloat_GrSLType, 0);
102 GrShaderVar gF("gF", kFloat2_GrSLType, 0);
103 GrShaderVar gFM("gFM", kFloat_GrSLType, 0);
104 GrShaderVar func("func", kFloat_GrSLType, 0);
105
106 fragBuilder->declAppend(edgeAlpha);
107 fragBuilder->declAppend(dklmdx);
108 fragBuilder->declAppend(dklmdy);
109 fragBuilder->declAppend(dfdx);
110 fragBuilder->declAppend(dfdy);
111 fragBuilder->declAppend(gF);
112 fragBuilder->declAppend(gFM);
113 fragBuilder->declAppend(func);
114
115 fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn());
116 fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn());
117 fragBuilder->codeAppendf("%s = 2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
118 dfdx.c_str(),
119 v.fsIn(), dklmdx.c_str(),
120 v.fsIn(), dklmdx.c_str(),
121 v.fsIn(), dklmdx.c_str());
122 fragBuilder->codeAppendf("%s = 2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
123 dfdy.c_str(),
124 v.fsIn(), dklmdy.c_str(),
125 v.fsIn(), dklmdy.c_str(),
126 v.fsIn(), dklmdy.c_str());
127 fragBuilder->codeAppendf("%s = float2(%s, %s);", gF.c_str(), dfdx.c_str(),
128 dfdy.c_str());
129 fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));",
130 gFM.c_str(), gF.c_str(), gF.c_str());
131 fragBuilder->codeAppendf("%s = %s.x*%s.x - %s.y*%s.z;",
132 func.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn());
133 fragBuilder->codeAppendf("%s = abs(%s);", func.c_str(), func.c_str());
134 fragBuilder->codeAppendf("%s = half(%s / %s);",
135 edgeAlpha.c_str(), func.c_str(), gFM.c_str());
136 fragBuilder->codeAppendf("%s = max(1.0 - %s, 0.0);",
137 edgeAlpha.c_str(), edgeAlpha.c_str());
138 // Add line below for smooth cubic ramp
139 // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);");
140
141 // TODO should we really be doing this?
142 if (gp.coverageScale() != 0xff) {
143 const char* coverageScale;
144 fCoverageScaleUniform = uniformHandler->addUniform(nullptr,
145 kFragment_GrShaderFlag,
146 kFloat_GrSLType,
147 "Coverage",
148 &coverageScale);
149 fragBuilder->codeAppendf("%s = half4(half(%s) * %s);",
150 args.fOutputCoverage, coverageScale, edgeAlpha.c_str());
151 } else {
152 fragBuilder->codeAppendf("%s = half4(%s);", args.fOutputCoverage, edgeAlpha.c_str());
153 }
154}
155
156void GrGLConicEffect::GenKey(const GrGeometryProcessor& gp,
157 const GrShaderCaps&,
158 GrProcessorKeyBuilder* b) {
159 const GrConicEffect& ce = gp.cast<GrConicEffect>();
160 uint32_t key = ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
161 key |= 0xff != ce.coverageScale() ? 0x8 : 0x0;
162 key |= ce.usesLocalCoords() ? 0x10 : 0x0;
163 key = AddMatrixKeys(key, ce.viewMatrix(), ce.usesLocalCoords() ? ce.localMatrix()
164 : SkMatrix::I());
165 b->add32(key);
166}
167
168//////////////////////////////////////////////////////////////////////////////
169
170constexpr GrPrimitiveProcessor::Attribute GrConicEffect::kAttributes[];
171
172GrConicEffect::~GrConicEffect() {}
173
174void GrConicEffect::getGLSLProcessorKey(const GrShaderCaps& caps,
175 GrProcessorKeyBuilder* b) const {
176 GrGLConicEffect::GenKey(*this, caps, b);
177}
178
179GrGLSLPrimitiveProcessor* GrConicEffect::createGLSLInstance(const GrShaderCaps&) const {
180 return new GrGLConicEffect(*this);
181}
182
183GrConicEffect::GrConicEffect(const SkPMColor4f& color, const SkMatrix& viewMatrix, uint8_t coverage,
184 const SkMatrix& localMatrix, bool usesLocalCoords)
185 : INHERITED(kGrConicEffect_ClassID)
186 , fColor(color)
187 , fViewMatrix(viewMatrix)
188 , fLocalMatrix(viewMatrix)
189 , fUsesLocalCoords(usesLocalCoords)
190 , fCoverageScale(coverage) {
191 this->setVertexAttributes(kAttributes, SK_ARRAY_COUNT(kAttributes));
192}
193
194//////////////////////////////////////////////////////////////////////////////
195
196GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrConicEffect);
197
198#if GR_TEST_UTILS
199GrGeometryProcessor* GrConicEffect::TestCreate(GrProcessorTestData* d) {
200 return GrConicEffect::Make(d->allocator(),
201 SkPMColor4f::FromBytes_RGBA(GrRandomColor(d->fRandom)),
202 GrTest::TestMatrix(d->fRandom), *d->caps(),
203 GrTest::TestMatrix(d->fRandom), d->fRandom->nextBool());
204}
205#endif
206
207//////////////////////////////////////////////////////////////////////////////
208// Quad
209//////////////////////////////////////////////////////////////////////////////
210
211class GrGLQuadEffect : public GrGLSLGeometryProcessor {
212public:
213 GrGLQuadEffect(const GrGeometryProcessor&);
214
215 void onEmitCode(EmitArgs&, GrGPArgs*) override;
216
217 static inline void GenKey(const GrGeometryProcessor&,
218 const GrShaderCaps&,
219 GrProcessorKeyBuilder*);
220
221 void setData(const GrGLSLProgramDataManager& pdman,
222 const GrPrimitiveProcessor& primProc) override {
223 const GrQuadEffect& qe = primProc.cast<GrQuadEffect>();
224
225 this->setTransform(pdman, fViewMatrixUniform, qe.viewMatrix(), &fViewMatrix);
226 this->setTransform(pdman, fLocalMatrixUniform, qe.localMatrix(), &fLocalMatrix);
227
228 if (qe.color() != fColor) {
229 pdman.set4fv(fColorUniform, 1, qe.color().vec());
230 fColor = qe.color();
231 }
232
233 if (qe.coverageScale() != 0xff && qe.coverageScale() != fCoverageScale) {
234 pdman.set1f(fCoverageScaleUniform, GrNormalizeByteToFloat(qe.coverageScale()));
235 fCoverageScale = qe.coverageScale();
236 }
237 }
238
239private:
240 SkMatrix fViewMatrix;
241 SkMatrix fLocalMatrix;
242 SkPMColor4f fColor;
243 uint8_t fCoverageScale;
244
245 UniformHandle fColorUniform;
246 UniformHandle fCoverageScaleUniform;
247 UniformHandle fViewMatrixUniform;
248 UniformHandle fLocalMatrixUniform;
249
250 typedef GrGLSLGeometryProcessor INHERITED;
251};
252
253GrGLQuadEffect::GrGLQuadEffect(const GrGeometryProcessor& processor)
254 : fViewMatrix(SkMatrix::InvalidMatrix())
255 , fLocalMatrix(SkMatrix::InvalidMatrix())
256 , fColor(SK_PMColor4fILLEGAL)
257 , fCoverageScale(0xff) {}
258
259void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
260 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
261 const GrQuadEffect& gp = args.fGP.cast<GrQuadEffect>();
262 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
263 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
264
265 // emit attributes
266 varyingHandler->emitAttributes(gp);
267
268 GrGLSLVarying v(kHalf4_GrSLType);
269 varyingHandler->addVarying("HairQuadEdge", &v);
270 vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inHairQuadEdge().name());
271
272 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
273 // Setup pass through color
274 this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform);
275
276 // Setup position
277 this->writeOutputPosition(vertBuilder,
278 uniformHandler,
279 gpArgs,
280 gp.inPosition().name(),
281 gp.viewMatrix(),
282 &fViewMatrixUniform);
283 if (gp.usesLocalCoords()) {
284 this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, gp.inPosition().asShaderVar(),
285 gp.localMatrix(), &fLocalMatrixUniform);
286 }
287
288 fragBuilder->codeAppendf("half edgeAlpha;");
289
290 fragBuilder->codeAppendf("half2 duvdx = half2(dFdx(%s.xy));", v.fsIn());
291 fragBuilder->codeAppendf("half2 duvdy = half2(dFdy(%s.xy));", v.fsIn());
292 fragBuilder->codeAppendf("half2 gF = half2(2.0 * %s.x * duvdx.x - duvdx.y,"
293 " 2.0 * %s.x * duvdy.x - duvdy.y);",
294 v.fsIn(), v.fsIn());
295 fragBuilder->codeAppendf("edgeAlpha = half(%s.x * %s.x - %s.y);",
296 v.fsIn(), v.fsIn(), v.fsIn());
297 fragBuilder->codeAppend("edgeAlpha = sqrt(edgeAlpha * edgeAlpha / dot(gF, gF));");
298 fragBuilder->codeAppend("edgeAlpha = max(1.0 - edgeAlpha, 0.0);");
299 // Add line below for smooth cubic ramp
300 // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);");
301
302 if (0xff != gp.coverageScale()) {
303 const char* coverageScale;
304 fCoverageScaleUniform = uniformHandler->addUniform(nullptr,
305 kFragment_GrShaderFlag,
306 kHalf_GrSLType,
307 "Coverage",
308 &coverageScale);
309 fragBuilder->codeAppendf("%s = half4(%s * edgeAlpha);", args.fOutputCoverage,
310 coverageScale);
311 } else {
312 fragBuilder->codeAppendf("%s = half4(edgeAlpha);", args.fOutputCoverage);
313 }
314}
315
316void GrGLQuadEffect::GenKey(const GrGeometryProcessor& gp,
317 const GrShaderCaps&,
318 GrProcessorKeyBuilder* b) {
319 const GrQuadEffect& ce = gp.cast<GrQuadEffect>();
320 uint32_t key = ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
321 key |= ce.coverageScale() != 0xff ? 0x8 : 0x0;
322 key |= ce.usesLocalCoords()? 0x10 : 0x0;
323 key = AddMatrixKeys(key, ce.viewMatrix(), ce.usesLocalCoords() ? ce.localMatrix()
324 : SkMatrix::I());
325 b->add32(key);
326}
327
328//////////////////////////////////////////////////////////////////////////////
329
330constexpr GrPrimitiveProcessor::Attribute GrQuadEffect::kAttributes[];
331
332GrQuadEffect::~GrQuadEffect() {}
333
334void GrQuadEffect::getGLSLProcessorKey(const GrShaderCaps& caps,
335 GrProcessorKeyBuilder* b) const {
336 GrGLQuadEffect::GenKey(*this, caps, b);
337}
338
339GrGLSLPrimitiveProcessor* GrQuadEffect::createGLSLInstance(const GrShaderCaps&) const {
340 return new GrGLQuadEffect(*this);
341}
342
343GrQuadEffect::GrQuadEffect(const SkPMColor4f& color, const SkMatrix& viewMatrix, uint8_t coverage,
344 const SkMatrix& localMatrix, bool usesLocalCoords)
345 : INHERITED(kGrQuadEffect_ClassID)
346 , fColor(color)
347 , fViewMatrix(viewMatrix)
348 , fLocalMatrix(localMatrix)
349 , fUsesLocalCoords(usesLocalCoords)
350 , fCoverageScale(coverage) {
351 this->setVertexAttributes(kAttributes, SK_ARRAY_COUNT(kAttributes));
352}
353
354//////////////////////////////////////////////////////////////////////////////
355
356GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrQuadEffect);
357
358#if GR_TEST_UTILS
359GrGeometryProcessor* GrQuadEffect::TestCreate(GrProcessorTestData* d) {
360 return GrQuadEffect::Make(d->allocator(),
361 SkPMColor4f::FromBytes_RGBA(GrRandomColor(d->fRandom)),
362 GrTest::TestMatrix(d->fRandom), *d->caps(),
363 GrTest::TestMatrix(d->fRandom), d->fRandom->nextBool());
364}
365#endif
366