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