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:
setData(const GrGLSLProgramDataManager & pdman,const GrShaderCaps & shaderCaps,const GrGeometryProcessor & geomProc)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
addToKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const154 void GrConicEffect::addToKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
155 uint32_t key = 0;
156 key |= fCoverageScale == 0xff ? 0x8 : 0x0;
157 key |= fUsesLocalCoords ? 0x10 : 0x0;
158 key = ProgramImpl::AddMatrixKeys(caps,
159 key,
160 fViewMatrix,
161 fUsesLocalCoords ? fLocalMatrix : SkMatrix::I());
162 b->add32(key);
163 }
164
makeProgramImpl(const GrShaderCaps &) const165 std::unique_ptr<GrGeometryProcessor::ProgramImpl> GrConicEffect::makeProgramImpl(
166 const GrShaderCaps&) const {
167 return std::make_unique<Impl>();
168 }
169
GrConicEffect(const SkPMColor4f & color,const SkMatrix & viewMatrix,uint8_t coverage,const SkMatrix & localMatrix,bool usesLocalCoords)170 GrConicEffect::GrConicEffect(const SkPMColor4f& color, const SkMatrix& viewMatrix, uint8_t coverage,
171 const SkMatrix& localMatrix, bool usesLocalCoords)
172 : INHERITED(kGrConicEffect_ClassID)
173 , fColor(color)
174 , fViewMatrix(viewMatrix)
175 , fLocalMatrix(viewMatrix)
176 , fUsesLocalCoords(usesLocalCoords)
177 , fCoverageScale(coverage) {
178 this->setVertexAttributes(kAttributes, SK_ARRAY_COUNT(kAttributes));
179 }
180
181 //////////////////////////////////////////////////////////////////////////////
182
183 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrConicEffect);
184
185 #if GR_TEST_UTILS
TestCreate(GrProcessorTestData * d)186 GrGeometryProcessor* GrConicEffect::TestCreate(GrProcessorTestData* d) {
187 GrColor color = GrTest::RandomColor(d->fRandom);
188 SkMatrix viewMatrix = GrTest::TestMatrix(d->fRandom);
189 SkMatrix localMatrix = GrTest::TestMatrix(d->fRandom);
190 bool usesLocalCoords = d->fRandom->nextBool();
191 return GrConicEffect::Make(d->allocator(),
192 SkPMColor4f::FromBytes_RGBA(color),
193 viewMatrix,
194 *d->caps(),
195 localMatrix,
196 usesLocalCoords);
197 }
198 #endif
199
200 //////////////////////////////////////////////////////////////////////////////
201 // Quad
202 //////////////////////////////////////////////////////////////////////////////
203
204 class GrQuadEffect::Impl : public ProgramImpl {
205 public:
setData(const GrGLSLProgramDataManager & pdman,const GrShaderCaps & shaderCaps,const GrGeometryProcessor & geomProc)206 void setData(const GrGLSLProgramDataManager& pdman,
207 const GrShaderCaps& shaderCaps,
208 const GrGeometryProcessor& geomProc) override {
209 const GrQuadEffect& qe = geomProc.cast<GrQuadEffect>();
210
211 SetTransform(pdman, shaderCaps, fViewMatrixUniform, qe.fViewMatrix, &fViewMatrix);
212 SetTransform(pdman, shaderCaps, fLocalMatrixUniform, qe.fLocalMatrix, &fLocalMatrix);
213
214 if (qe.fColor != fColor) {
215 pdman.set4fv(fColorUniform, 1, qe.fColor.vec());
216 fColor = qe.fColor;
217 }
218
219 if (qe.fCoverageScale != 0xff && qe.fCoverageScale != fCoverageScale) {
220 pdman.set1f(fCoverageScaleUniform, GrNormalizeByteToFloat(qe.fCoverageScale));
221 fCoverageScale = qe.fCoverageScale;
222 }
223 }
224
225 private:
226 void onEmitCode(EmitArgs&, GrGPArgs*) override;
227
228 SkMatrix fViewMatrix = SkMatrix::InvalidMatrix();
229 SkMatrix fLocalMatrix = SkMatrix::InvalidMatrix();
230 SkPMColor4f fColor = SK_PMColor4fILLEGAL;
231 uint8_t fCoverageScale = 0xFF;
232
233 UniformHandle fColorUniform;
234 UniformHandle fCoverageScaleUniform;
235 UniformHandle fViewMatrixUniform;
236 UniformHandle fLocalMatrixUniform;
237 };
238
onEmitCode(EmitArgs & args,GrGPArgs * gpArgs)239 void GrQuadEffect::Impl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
240 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
241 const GrQuadEffect& gp = args.fGeomProc.cast<GrQuadEffect>();
242 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
243 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
244
245 // emit attributes
246 varyingHandler->emitAttributes(gp);
247
248 GrGLSLVarying v(kHalf4_GrSLType);
249 varyingHandler->addVarying("HairQuadEdge", &v);
250 vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inHairQuadEdge().name());
251
252 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
253 // Setup pass through color
254 fragBuilder->codeAppendf("half4 %s;", args.fOutputColor);
255 this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform);
256
257 // Setup position
258 WriteOutputPosition(vertBuilder,
259 uniformHandler,
260 *args.fShaderCaps,
261 gpArgs,
262 gp.inPosition().name(),
263 gp.fViewMatrix,
264 &fViewMatrixUniform);
265 if (gp.fUsesLocalCoords) {
266 WriteLocalCoord(vertBuilder,
267 uniformHandler,
268 *args.fShaderCaps,
269 gpArgs,
270 gp.inPosition().asShaderVar(),
271 gp.fLocalMatrix,
272 &fLocalMatrixUniform);
273 }
274
275 fragBuilder->codeAppendf("half edgeAlpha;");
276
277 fragBuilder->codeAppendf("half2 duvdx = half2(dFdx(%s.xy));", v.fsIn());
278 fragBuilder->codeAppendf("half2 duvdy = half2(dFdy(%s.xy));", v.fsIn());
279 fragBuilder->codeAppendf("half2 gF = half2(2.0 * %s.x * duvdx.x - duvdx.y,"
280 " 2.0 * %s.x * duvdy.x - duvdy.y);",
281 v.fsIn(), v.fsIn());
282 fragBuilder->codeAppendf("edgeAlpha = half(%s.x * %s.x - %s.y);",
283 v.fsIn(), v.fsIn(), v.fsIn());
284 fragBuilder->codeAppend("edgeAlpha = sqrt(edgeAlpha * edgeAlpha / dot(gF, gF));");
285 fragBuilder->codeAppend("edgeAlpha = max(1.0 - edgeAlpha, 0.0);");
286 // Add line below for smooth cubic ramp
287 // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);");
288
289 if (gp.fCoverageScale != 0xFF) {
290 const char* coverageScale;
291 fCoverageScaleUniform = uniformHandler->addUniform(nullptr,
292 kFragment_GrShaderFlag,
293 kHalf_GrSLType,
294 "Coverage",
295 &coverageScale);
296 fragBuilder->codeAppendf("half4 %s = half4(%s * edgeAlpha);", args.fOutputCoverage,
297 coverageScale);
298 } else {
299 fragBuilder->codeAppendf("half4 %s = half4(edgeAlpha);", args.fOutputCoverage);
300 }
301 }
302
303 //////////////////////////////////////////////////////////////////////////////
304
305 GrQuadEffect::~GrQuadEffect() = default;
306
addToKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const307 void GrQuadEffect::addToKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
308 uint32_t key = 0;
309 key |= fCoverageScale != 0xff ? 0x8 : 0x0;
310 key |= fUsesLocalCoords ? 0x10 : 0x0;
311 key = ProgramImpl::AddMatrixKeys(caps,
312 key,
313 fViewMatrix,
314 fUsesLocalCoords ? fLocalMatrix : SkMatrix::I());
315 b->add32(key);
316 }
317
makeProgramImpl(const GrShaderCaps &) const318 std::unique_ptr<GrGeometryProcessor::ProgramImpl> GrQuadEffect::makeProgramImpl(
319 const GrShaderCaps&) const {
320 return std::make_unique<Impl>();
321 }
322
GrQuadEffect(const SkPMColor4f & color,const SkMatrix & viewMatrix,uint8_t coverage,const SkMatrix & localMatrix,bool usesLocalCoords)323 GrQuadEffect::GrQuadEffect(const SkPMColor4f& color, const SkMatrix& viewMatrix, uint8_t coverage,
324 const SkMatrix& localMatrix, bool usesLocalCoords)
325 : INHERITED(kGrQuadEffect_ClassID)
326 , fColor(color)
327 , fViewMatrix(viewMatrix)
328 , fLocalMatrix(localMatrix)
329 , fUsesLocalCoords(usesLocalCoords)
330 , fCoverageScale(coverage) {
331 this->setVertexAttributes(kAttributes, SK_ARRAY_COUNT(kAttributes));
332 }
333
334 //////////////////////////////////////////////////////////////////////////////
335
336 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrQuadEffect);
337
338 #if GR_TEST_UTILS
TestCreate(GrProcessorTestData * d)339 GrGeometryProcessor* GrQuadEffect::TestCreate(GrProcessorTestData* d) {
340 GrColor color = GrTest::RandomColor(d->fRandom);
341 SkMatrix viewMatrix = GrTest::TestMatrix(d->fRandom);
342 SkMatrix localMatrix = GrTest::TestMatrix(d->fRandom);
343 bool usesLocalCoords = d->fRandom->nextBool();
344 return GrQuadEffect::Make(d->allocator(),
345 SkPMColor4f::FromBytes_RGBA(color),
346 viewMatrix,
347 *d->caps(),
348 localMatrix,
349 usesLocalCoords);
350 }
351 #endif
352