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