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