1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2015 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 #include "src/gpu/ganesh/glsl/GrGLSLProgramBuilder.h"
8*c8dee2aaSAndroid Build Coastguard Worker
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSpan.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrTypes.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTemplates.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkSLTypeShared.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrFragmentProcessor.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrGeometryProcessor.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrPipeline.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrResourceHandle.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrShaderCaps.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSurfaceProxy.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSurfaceProxyView.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrTextureProxy.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrXferProcessor.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/effects/GrTextureEffect.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/glsl/GrGLSLVarying.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLCompiler.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLString.h"
28*c8dee2aaSAndroid Build Coastguard Worker
29*c8dee2aaSAndroid Build Coastguard Worker #include <functional>
30*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
31*c8dee2aaSAndroid Build Coastguard Worker #include <tuple>
32*c8dee2aaSAndroid Build Coastguard Worker #include <unordered_map>
33*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
34*c8dee2aaSAndroid Build Coastguard Worker
35*c8dee2aaSAndroid Build Coastguard Worker
36*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
37*c8dee2aaSAndroid Build Coastguard Worker
38*c8dee2aaSAndroid Build Coastguard Worker const int GrGLSLProgramBuilder::kVarsPerBlock = 8;
39*c8dee2aaSAndroid Build Coastguard Worker
GrGLSLProgramBuilder(const GrProgramDesc & desc,const GrProgramInfo & programInfo)40*c8dee2aaSAndroid Build Coastguard Worker GrGLSLProgramBuilder::GrGLSLProgramBuilder(const GrProgramDesc& desc,
41*c8dee2aaSAndroid Build Coastguard Worker const GrProgramInfo& programInfo)
42*c8dee2aaSAndroid Build Coastguard Worker : fVS(this)
43*c8dee2aaSAndroid Build Coastguard Worker , fFS(this)
44*c8dee2aaSAndroid Build Coastguard Worker , fDesc(desc)
45*c8dee2aaSAndroid Build Coastguard Worker , fProgramInfo(programInfo)
46*c8dee2aaSAndroid Build Coastguard Worker , fNumFragmentSamplers(0) {}
47*c8dee2aaSAndroid Build Coastguard Worker
48*c8dee2aaSAndroid Build Coastguard Worker GrGLSLProgramBuilder::~GrGLSLProgramBuilder() = default;
49*c8dee2aaSAndroid Build Coastguard Worker
addFeature(GrShaderFlags shaders,uint32_t featureBit,const char * extensionName)50*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLProgramBuilder::addFeature(GrShaderFlags shaders,
51*c8dee2aaSAndroid Build Coastguard Worker uint32_t featureBit,
52*c8dee2aaSAndroid Build Coastguard Worker const char* extensionName) {
53*c8dee2aaSAndroid Build Coastguard Worker if (shaders & kVertex_GrShaderFlag) {
54*c8dee2aaSAndroid Build Coastguard Worker fVS.addFeature(featureBit, extensionName);
55*c8dee2aaSAndroid Build Coastguard Worker }
56*c8dee2aaSAndroid Build Coastguard Worker if (shaders & kFragment_GrShaderFlag) {
57*c8dee2aaSAndroid Build Coastguard Worker fFS.addFeature(featureBit, extensionName);
58*c8dee2aaSAndroid Build Coastguard Worker }
59*c8dee2aaSAndroid Build Coastguard Worker }
60*c8dee2aaSAndroid Build Coastguard Worker
emitAndInstallProcs()61*c8dee2aaSAndroid Build Coastguard Worker bool GrGLSLProgramBuilder::emitAndInstallProcs() {
62*c8dee2aaSAndroid Build Coastguard Worker // First we loop over all of the installed processors and collect coord transforms. These will
63*c8dee2aaSAndroid Build Coastguard Worker // be sent to the ProgramImpl in its emitCode function
64*c8dee2aaSAndroid Build Coastguard Worker SkString inputColor;
65*c8dee2aaSAndroid Build Coastguard Worker SkString inputCoverage;
66*c8dee2aaSAndroid Build Coastguard Worker if (!this->emitAndInstallPrimProc(&inputColor, &inputCoverage)) {
67*c8dee2aaSAndroid Build Coastguard Worker return false;
68*c8dee2aaSAndroid Build Coastguard Worker }
69*c8dee2aaSAndroid Build Coastguard Worker if (!this->emitAndInstallDstTexture()) {
70*c8dee2aaSAndroid Build Coastguard Worker return false;
71*c8dee2aaSAndroid Build Coastguard Worker }
72*c8dee2aaSAndroid Build Coastguard Worker if (!this->emitAndInstallFragProcs(&inputColor, &inputCoverage)) {
73*c8dee2aaSAndroid Build Coastguard Worker return false;
74*c8dee2aaSAndroid Build Coastguard Worker }
75*c8dee2aaSAndroid Build Coastguard Worker if (!this->emitAndInstallXferProc(inputColor, inputCoverage)) {
76*c8dee2aaSAndroid Build Coastguard Worker return false;
77*c8dee2aaSAndroid Build Coastguard Worker }
78*c8dee2aaSAndroid Build Coastguard Worker fGPImpl->emitTransformCode(&fVS, this->uniformHandler());
79*c8dee2aaSAndroid Build Coastguard Worker
80*c8dee2aaSAndroid Build Coastguard Worker return this->checkSamplerCounts();
81*c8dee2aaSAndroid Build Coastguard Worker }
82*c8dee2aaSAndroid Build Coastguard Worker
emitAndInstallPrimProc(SkString * outputColor,SkString * outputCoverage)83*c8dee2aaSAndroid Build Coastguard Worker bool GrGLSLProgramBuilder::emitAndInstallPrimProc(SkString* outputColor, SkString* outputCoverage) {
84*c8dee2aaSAndroid Build Coastguard Worker const GrGeometryProcessor& geomProc = this->geometryProcessor();
85*c8dee2aaSAndroid Build Coastguard Worker
86*c8dee2aaSAndroid Build Coastguard Worker // Program builders have a bit of state we need to clear with each effect
87*c8dee2aaSAndroid Build Coastguard Worker this->advanceStage();
88*c8dee2aaSAndroid Build Coastguard Worker this->nameExpression(outputColor, "outputColor");
89*c8dee2aaSAndroid Build Coastguard Worker this->nameExpression(outputCoverage, "outputCoverage");
90*c8dee2aaSAndroid Build Coastguard Worker
91*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fUniformHandles.fRTAdjustmentUni.isValid());
92*c8dee2aaSAndroid Build Coastguard Worker fUniformHandles.fRTAdjustmentUni = this->uniformHandler()->addUniform(
93*c8dee2aaSAndroid Build Coastguard Worker nullptr, kVertex_GrShaderFlag, SkSLType::kFloat4, SkSL::Compiler::RTADJUST_NAME);
94*c8dee2aaSAndroid Build Coastguard Worker
95*c8dee2aaSAndroid Build Coastguard Worker fFS.codeAppendf("// Stage %d, %s\n", fStageIndex, geomProc.name());
96*c8dee2aaSAndroid Build Coastguard Worker fVS.codeAppendf("// Primitive Processor %s\n", geomProc.name());
97*c8dee2aaSAndroid Build Coastguard Worker
98*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fGPImpl);
99*c8dee2aaSAndroid Build Coastguard Worker fGPImpl = geomProc.makeProgramImpl(*this->shaderCaps());
100*c8dee2aaSAndroid Build Coastguard Worker
101*c8dee2aaSAndroid Build Coastguard Worker AutoSTArray<4, SamplerHandle> texSamplers(geomProc.numTextureSamplers());
102*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < geomProc.numTextureSamplers(); ++i) {
103*c8dee2aaSAndroid Build Coastguard Worker SkString name;
104*c8dee2aaSAndroid Build Coastguard Worker name.printf("TextureSampler_%d", i);
105*c8dee2aaSAndroid Build Coastguard Worker const auto& sampler = geomProc.textureSampler(i);
106*c8dee2aaSAndroid Build Coastguard Worker texSamplers[i] = this->emitSampler(sampler.backendFormat(),
107*c8dee2aaSAndroid Build Coastguard Worker sampler.samplerState(),
108*c8dee2aaSAndroid Build Coastguard Worker sampler.swizzle(),
109*c8dee2aaSAndroid Build Coastguard Worker name.c_str());
110*c8dee2aaSAndroid Build Coastguard Worker if (!texSamplers[i].isValid()) {
111*c8dee2aaSAndroid Build Coastguard Worker return false;
112*c8dee2aaSAndroid Build Coastguard Worker }
113*c8dee2aaSAndroid Build Coastguard Worker }
114*c8dee2aaSAndroid Build Coastguard Worker
115*c8dee2aaSAndroid Build Coastguard Worker GrGeometryProcessor::ProgramImpl::EmitArgs args(&fVS,
116*c8dee2aaSAndroid Build Coastguard Worker &fFS,
117*c8dee2aaSAndroid Build Coastguard Worker this->varyingHandler(),
118*c8dee2aaSAndroid Build Coastguard Worker this->uniformHandler(),
119*c8dee2aaSAndroid Build Coastguard Worker this->shaderCaps(),
120*c8dee2aaSAndroid Build Coastguard Worker geomProc,
121*c8dee2aaSAndroid Build Coastguard Worker outputColor->c_str(),
122*c8dee2aaSAndroid Build Coastguard Worker outputCoverage->c_str(),
123*c8dee2aaSAndroid Build Coastguard Worker texSamplers.get());
124*c8dee2aaSAndroid Build Coastguard Worker std::tie(fFPCoordsMap, fLocalCoordsVar) = fGPImpl->emitCode(args, this->pipeline());
125*c8dee2aaSAndroid Build Coastguard Worker
126*c8dee2aaSAndroid Build Coastguard Worker // We have to check that effects and the code they emit are consistent, ie if an effect
127*c8dee2aaSAndroid Build Coastguard Worker // asks for dst color, then the emit code needs to follow suit
128*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(verify(geomProc);)
129*c8dee2aaSAndroid Build Coastguard Worker
130*c8dee2aaSAndroid Build Coastguard Worker return true;
131*c8dee2aaSAndroid Build Coastguard Worker }
132*c8dee2aaSAndroid Build Coastguard Worker
emitAndInstallFragProcs(SkString * color,SkString * coverage)133*c8dee2aaSAndroid Build Coastguard Worker bool GrGLSLProgramBuilder::emitAndInstallFragProcs(SkString* color, SkString* coverage) {
134*c8dee2aaSAndroid Build Coastguard Worker int fpCount = this->pipeline().numFragmentProcessors();
135*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fFPImpls.empty());
136*c8dee2aaSAndroid Build Coastguard Worker fFPImpls.reserve(fpCount);
137*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < fpCount; ++i) {
138*c8dee2aaSAndroid Build Coastguard Worker SkString* inOut = this->pipeline().isColorFragmentProcessor(i) ? color : coverage;
139*c8dee2aaSAndroid Build Coastguard Worker SkString output;
140*c8dee2aaSAndroid Build Coastguard Worker const GrFragmentProcessor& fp = this->pipeline().getFragmentProcessor(i);
141*c8dee2aaSAndroid Build Coastguard Worker fFPImpls.push_back(fp.makeProgramImpl());
142*c8dee2aaSAndroid Build Coastguard Worker output = this->emitRootFragProc(fp, *fFPImpls.back(), *inOut, output);
143*c8dee2aaSAndroid Build Coastguard Worker if (output.isEmpty()) {
144*c8dee2aaSAndroid Build Coastguard Worker return false;
145*c8dee2aaSAndroid Build Coastguard Worker }
146*c8dee2aaSAndroid Build Coastguard Worker *inOut = std::move(output);
147*c8dee2aaSAndroid Build Coastguard Worker }
148*c8dee2aaSAndroid Build Coastguard Worker return true;
149*c8dee2aaSAndroid Build Coastguard Worker }
150*c8dee2aaSAndroid Build Coastguard Worker
emitTextureSamplersForFPs(const GrFragmentProcessor & fp,GrFragmentProcessor::ProgramImpl & impl,int * samplerIndex)151*c8dee2aaSAndroid Build Coastguard Worker bool GrGLSLProgramBuilder::emitTextureSamplersForFPs(const GrFragmentProcessor& fp,
152*c8dee2aaSAndroid Build Coastguard Worker GrFragmentProcessor::ProgramImpl& impl,
153*c8dee2aaSAndroid Build Coastguard Worker int* samplerIndex) {
154*c8dee2aaSAndroid Build Coastguard Worker bool ok = true;
155*c8dee2aaSAndroid Build Coastguard Worker fp.visitWithImpls([&](const GrFragmentProcessor& fp, GrFragmentProcessor::ProgramImpl& impl) {
156*c8dee2aaSAndroid Build Coastguard Worker if (const GrTextureEffect* te = fp.asTextureEffect()) {
157*c8dee2aaSAndroid Build Coastguard Worker SkString name = SkStringPrintf("TextureSampler_%d", *samplerIndex);
158*c8dee2aaSAndroid Build Coastguard Worker *samplerIndex += 1;
159*c8dee2aaSAndroid Build Coastguard Worker
160*c8dee2aaSAndroid Build Coastguard Worker GrSamplerState samplerState = te->samplerState();
161*c8dee2aaSAndroid Build Coastguard Worker const GrBackendFormat& format = te->view().proxy()->backendFormat();
162*c8dee2aaSAndroid Build Coastguard Worker skgpu::Swizzle swizzle = te->view().swizzle();
163*c8dee2aaSAndroid Build Coastguard Worker SamplerHandle handle = this->emitSampler(format, samplerState, swizzle, name.c_str());
164*c8dee2aaSAndroid Build Coastguard Worker if (!handle.isValid()) {
165*c8dee2aaSAndroid Build Coastguard Worker ok = false;
166*c8dee2aaSAndroid Build Coastguard Worker return;
167*c8dee2aaSAndroid Build Coastguard Worker }
168*c8dee2aaSAndroid Build Coastguard Worker static_cast<GrTextureEffect::Impl&>(impl).setSamplerHandle(handle);
169*c8dee2aaSAndroid Build Coastguard Worker }
170*c8dee2aaSAndroid Build Coastguard Worker }, impl);
171*c8dee2aaSAndroid Build Coastguard Worker
172*c8dee2aaSAndroid Build Coastguard Worker return ok;
173*c8dee2aaSAndroid Build Coastguard Worker }
174*c8dee2aaSAndroid Build Coastguard Worker
invokeFP(const GrFragmentProcessor & fp,const GrFragmentProcessor::ProgramImpl & impl,const char * inputColor,const char * destColor,const char * coords) const175*c8dee2aaSAndroid Build Coastguard Worker std::string GrGLSLProgramBuilder::invokeFP(const GrFragmentProcessor& fp,
176*c8dee2aaSAndroid Build Coastguard Worker const GrFragmentProcessor::ProgramImpl& impl,
177*c8dee2aaSAndroid Build Coastguard Worker const char* inputColor,
178*c8dee2aaSAndroid Build Coastguard Worker const char* destColor,
179*c8dee2aaSAndroid Build Coastguard Worker const char* coords) const {
180*c8dee2aaSAndroid Build Coastguard Worker if (fp.isBlendFunction()) {
181*c8dee2aaSAndroid Build Coastguard Worker if (this->fragmentProcessorHasCoordsParam(&fp)) {
182*c8dee2aaSAndroid Build Coastguard Worker return SkSL::String::printf("%s(%s, %s, %s)", impl.functionName(), inputColor,
183*c8dee2aaSAndroid Build Coastguard Worker destColor, coords);
184*c8dee2aaSAndroid Build Coastguard Worker } else {
185*c8dee2aaSAndroid Build Coastguard Worker return SkSL::String::printf("%s(%s, %s)", impl.functionName(), inputColor, destColor);
186*c8dee2aaSAndroid Build Coastguard Worker }
187*c8dee2aaSAndroid Build Coastguard Worker }
188*c8dee2aaSAndroid Build Coastguard Worker
189*c8dee2aaSAndroid Build Coastguard Worker if (this->fragmentProcessorHasCoordsParam(&fp)) {
190*c8dee2aaSAndroid Build Coastguard Worker return SkSL::String::printf("%s(%s, %s)", impl.functionName(), inputColor, coords);
191*c8dee2aaSAndroid Build Coastguard Worker } else {
192*c8dee2aaSAndroid Build Coastguard Worker return SkSL::String::printf("%s(%s)", impl.functionName(), inputColor);
193*c8dee2aaSAndroid Build Coastguard Worker }
194*c8dee2aaSAndroid Build Coastguard Worker }
195*c8dee2aaSAndroid Build Coastguard Worker
emitRootFragProc(const GrFragmentProcessor & fp,GrFragmentProcessor::ProgramImpl & impl,const SkString & input,SkString output)196*c8dee2aaSAndroid Build Coastguard Worker SkString GrGLSLProgramBuilder::emitRootFragProc(const GrFragmentProcessor& fp,
197*c8dee2aaSAndroid Build Coastguard Worker GrFragmentProcessor::ProgramImpl& impl,
198*c8dee2aaSAndroid Build Coastguard Worker const SkString& input,
199*c8dee2aaSAndroid Build Coastguard Worker SkString output) {
200*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(input.size());
201*c8dee2aaSAndroid Build Coastguard Worker
202*c8dee2aaSAndroid Build Coastguard Worker // Program builders have a bit of state we need to clear with each effect
203*c8dee2aaSAndroid Build Coastguard Worker this->advanceStage();
204*c8dee2aaSAndroid Build Coastguard Worker this->nameExpression(&output, "output");
205*c8dee2aaSAndroid Build Coastguard Worker fFS.codeAppendf("half4 %s;", output.c_str());
206*c8dee2aaSAndroid Build Coastguard Worker int samplerIndex = 0;
207*c8dee2aaSAndroid Build Coastguard Worker if (!this->emitTextureSamplersForFPs(fp, impl, &samplerIndex)) {
208*c8dee2aaSAndroid Build Coastguard Worker return {};
209*c8dee2aaSAndroid Build Coastguard Worker }
210*c8dee2aaSAndroid Build Coastguard Worker
211*c8dee2aaSAndroid Build Coastguard Worker this->writeFPFunction(fp, impl);
212*c8dee2aaSAndroid Build Coastguard Worker
213*c8dee2aaSAndroid Build Coastguard Worker fFS.codeAppendf(
214*c8dee2aaSAndroid Build Coastguard Worker "%s = %s;",
215*c8dee2aaSAndroid Build Coastguard Worker output.c_str(),
216*c8dee2aaSAndroid Build Coastguard Worker this->invokeFP(fp, impl, input.c_str(), "half4(1)", fLocalCoordsVar.c_str()).c_str());
217*c8dee2aaSAndroid Build Coastguard Worker
218*c8dee2aaSAndroid Build Coastguard Worker // We have to check that effects and the code they emit are consistent, ie if an effect asks
219*c8dee2aaSAndroid Build Coastguard Worker // for dst color, then the emit code needs to follow suit
220*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(verify(fp);)
221*c8dee2aaSAndroid Build Coastguard Worker
222*c8dee2aaSAndroid Build Coastguard Worker return output;
223*c8dee2aaSAndroid Build Coastguard Worker }
224*c8dee2aaSAndroid Build Coastguard Worker
writeChildFPFunctions(const GrFragmentProcessor & fp,GrFragmentProcessor::ProgramImpl & impl)225*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLProgramBuilder::writeChildFPFunctions(const GrFragmentProcessor& fp,
226*c8dee2aaSAndroid Build Coastguard Worker GrFragmentProcessor::ProgramImpl& impl) {
227*c8dee2aaSAndroid Build Coastguard Worker fSubstageIndices.push_back(0);
228*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < impl.numChildProcessors(); ++i) {
229*c8dee2aaSAndroid Build Coastguard Worker GrFragmentProcessor::ProgramImpl* childImpl = impl.childProcessor(i);
230*c8dee2aaSAndroid Build Coastguard Worker if (!childImpl) {
231*c8dee2aaSAndroid Build Coastguard Worker continue;
232*c8dee2aaSAndroid Build Coastguard Worker }
233*c8dee2aaSAndroid Build Coastguard Worker
234*c8dee2aaSAndroid Build Coastguard Worker const GrFragmentProcessor* childFP = fp.childProcessor(i);
235*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(childFP);
236*c8dee2aaSAndroid Build Coastguard Worker
237*c8dee2aaSAndroid Build Coastguard Worker this->writeFPFunction(*childFP, *childImpl);
238*c8dee2aaSAndroid Build Coastguard Worker ++fSubstageIndices.back();
239*c8dee2aaSAndroid Build Coastguard Worker }
240*c8dee2aaSAndroid Build Coastguard Worker fSubstageIndices.pop_back();
241*c8dee2aaSAndroid Build Coastguard Worker }
242*c8dee2aaSAndroid Build Coastguard Worker
writeFPFunction(const GrFragmentProcessor & fp,GrFragmentProcessor::ProgramImpl & impl)243*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLProgramBuilder::writeFPFunction(const GrFragmentProcessor& fp,
244*c8dee2aaSAndroid Build Coastguard Worker GrFragmentProcessor::ProgramImpl& impl) {
245*c8dee2aaSAndroid Build Coastguard Worker constexpr const char* kDstColor = "_dst";
246*c8dee2aaSAndroid Build Coastguard Worker const char* const inputColor = fp.isBlendFunction() ? "_src" : "_input";
247*c8dee2aaSAndroid Build Coastguard Worker const char* sampleCoords = "_coords";
248*c8dee2aaSAndroid Build Coastguard Worker fFS.nextStage();
249*c8dee2aaSAndroid Build Coastguard Worker // Conceptually, an FP is always sampled at a particular coordinate. However, if it is only
250*c8dee2aaSAndroid Build Coastguard Worker // sampled by a chain of uniform matrix expressions (or legacy coord transforms), the value that
251*c8dee2aaSAndroid Build Coastguard Worker // would have been passed to _coords is lifted to the vertex shader and
252*c8dee2aaSAndroid Build Coastguard Worker // varying. In that case it uses that variable and we do not pass a second argument for _coords.
253*c8dee2aaSAndroid Build Coastguard Worker GrShaderVar params[3];
254*c8dee2aaSAndroid Build Coastguard Worker int numParams = 0;
255*c8dee2aaSAndroid Build Coastguard Worker
256*c8dee2aaSAndroid Build Coastguard Worker params[numParams++] = GrShaderVar(inputColor, SkSLType::kHalf4);
257*c8dee2aaSAndroid Build Coastguard Worker
258*c8dee2aaSAndroid Build Coastguard Worker if (fp.isBlendFunction()) {
259*c8dee2aaSAndroid Build Coastguard Worker // Blend functions take a dest color as input.
260*c8dee2aaSAndroid Build Coastguard Worker params[numParams++] = GrShaderVar(kDstColor, SkSLType::kHalf4);
261*c8dee2aaSAndroid Build Coastguard Worker }
262*c8dee2aaSAndroid Build Coastguard Worker
263*c8dee2aaSAndroid Build Coastguard Worker auto fpCoordsIter = fFPCoordsMap.find(&fp);
264*c8dee2aaSAndroid Build Coastguard Worker if (fpCoordsIter == fFPCoordsMap.end()) {
265*c8dee2aaSAndroid Build Coastguard Worker // This FP isn't in our coords map at all, so its coords (if any) couldn't have been lifted
266*c8dee2aaSAndroid Build Coastguard Worker // to a varying.
267*c8dee2aaSAndroid Build Coastguard Worker if (fp.usesSampleCoords()) {
268*c8dee2aaSAndroid Build Coastguard Worker params[numParams++] = GrShaderVar(sampleCoords, SkSLType::kFloat2);
269*c8dee2aaSAndroid Build Coastguard Worker }
270*c8dee2aaSAndroid Build Coastguard Worker } else if (fpCoordsIter->second.hasCoordsParam) {
271*c8dee2aaSAndroid Build Coastguard Worker // This FP is in our map, and it takes an explicit coords param.
272*c8dee2aaSAndroid Build Coastguard Worker params[numParams++] = GrShaderVar(sampleCoords, SkSLType::kFloat2);
273*c8dee2aaSAndroid Build Coastguard Worker } else {
274*c8dee2aaSAndroid Build Coastguard Worker // Either doesn't use coords at all or sampled through a chain of passthrough/matrix
275*c8dee2aaSAndroid Build Coastguard Worker // samples usages. In the latter case the coords are emitted in the vertex shader as a
276*c8dee2aaSAndroid Build Coastguard Worker // varying, so this only has to access it. Add a float2 _coords variable that maps to the
277*c8dee2aaSAndroid Build Coastguard Worker // associated varying and replaces the absent 2nd argument to the fp's function.
278*c8dee2aaSAndroid Build Coastguard Worker GrShaderVar varying = fpCoordsIter->second.coordsVarying;
279*c8dee2aaSAndroid Build Coastguard Worker
280*c8dee2aaSAndroid Build Coastguard Worker switch (varying.getType()) {
281*c8dee2aaSAndroid Build Coastguard Worker case SkSLType::kVoid:
282*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fp.usesSampleCoordsDirectly());
283*c8dee2aaSAndroid Build Coastguard Worker break;
284*c8dee2aaSAndroid Build Coastguard Worker case SkSLType::kFloat2:
285*c8dee2aaSAndroid Build Coastguard Worker // Just point the local coords to the varying
286*c8dee2aaSAndroid Build Coastguard Worker sampleCoords = varying.getName().c_str();
287*c8dee2aaSAndroid Build Coastguard Worker break;
288*c8dee2aaSAndroid Build Coastguard Worker case SkSLType::kFloat3:
289*c8dee2aaSAndroid Build Coastguard Worker // Must perform the perspective divide in the frag shader based on the
290*c8dee2aaSAndroid Build Coastguard Worker // varying, and since we won't actually have a function parameter for local
291*c8dee2aaSAndroid Build Coastguard Worker // coords, add it as a local variable.
292*c8dee2aaSAndroid Build Coastguard Worker fFS.codeAppendf("float2 %s = %s.xy / %s.z;\n",
293*c8dee2aaSAndroid Build Coastguard Worker sampleCoords,
294*c8dee2aaSAndroid Build Coastguard Worker varying.getName().c_str(),
295*c8dee2aaSAndroid Build Coastguard Worker varying.getName().c_str());
296*c8dee2aaSAndroid Build Coastguard Worker break;
297*c8dee2aaSAndroid Build Coastguard Worker default:
298*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGFAILF("Unexpected varying type for coord: %s %d\n",
299*c8dee2aaSAndroid Build Coastguard Worker varying.getName().c_str(),
300*c8dee2aaSAndroid Build Coastguard Worker (int)varying.getType());
301*c8dee2aaSAndroid Build Coastguard Worker break;
302*c8dee2aaSAndroid Build Coastguard Worker }
303*c8dee2aaSAndroid Build Coastguard Worker }
304*c8dee2aaSAndroid Build Coastguard Worker
305*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(numParams <= (int)std::size(params));
306*c8dee2aaSAndroid Build Coastguard Worker
307*c8dee2aaSAndroid Build Coastguard Worker // First, emit every child's function. This needs to happen (even for children that aren't
308*c8dee2aaSAndroid Build Coastguard Worker // sampled), so that all of the expected uniforms are registered.
309*c8dee2aaSAndroid Build Coastguard Worker this->writeChildFPFunctions(fp, impl);
310*c8dee2aaSAndroid Build Coastguard Worker GrFragmentProcessor::ProgramImpl::EmitArgs args(&fFS,
311*c8dee2aaSAndroid Build Coastguard Worker this->uniformHandler(),
312*c8dee2aaSAndroid Build Coastguard Worker this->shaderCaps(),
313*c8dee2aaSAndroid Build Coastguard Worker fp,
314*c8dee2aaSAndroid Build Coastguard Worker inputColor,
315*c8dee2aaSAndroid Build Coastguard Worker kDstColor,
316*c8dee2aaSAndroid Build Coastguard Worker sampleCoords);
317*c8dee2aaSAndroid Build Coastguard Worker
318*c8dee2aaSAndroid Build Coastguard Worker impl.emitCode(args);
319*c8dee2aaSAndroid Build Coastguard Worker impl.setFunctionName(fFS.getMangledFunctionName(args.fFp.name()));
320*c8dee2aaSAndroid Build Coastguard Worker
321*c8dee2aaSAndroid Build Coastguard Worker fFS.emitFunction(SkSLType::kHalf4,
322*c8dee2aaSAndroid Build Coastguard Worker impl.functionName(),
323*c8dee2aaSAndroid Build Coastguard Worker SkSpan(params, numParams),
324*c8dee2aaSAndroid Build Coastguard Worker fFS.code().c_str());
325*c8dee2aaSAndroid Build Coastguard Worker fFS.deleteStage();
326*c8dee2aaSAndroid Build Coastguard Worker }
327*c8dee2aaSAndroid Build Coastguard Worker
emitAndInstallDstTexture()328*c8dee2aaSAndroid Build Coastguard Worker bool GrGLSLProgramBuilder::emitAndInstallDstTexture() {
329*c8dee2aaSAndroid Build Coastguard Worker fDstTextureOrigin = kTopLeft_GrSurfaceOrigin;
330*c8dee2aaSAndroid Build Coastguard Worker
331*c8dee2aaSAndroid Build Coastguard Worker const GrSurfaceProxyView& dstView = this->pipeline().dstProxyView();
332*c8dee2aaSAndroid Build Coastguard Worker if (this->pipeline().usesDstTexture()) {
333*c8dee2aaSAndroid Build Coastguard Worker // Set up a sampler handle for the destination texture.
334*c8dee2aaSAndroid Build Coastguard Worker GrTextureProxy* dstTextureProxy = dstView.asTextureProxy();
335*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(dstTextureProxy);
336*c8dee2aaSAndroid Build Coastguard Worker const skgpu::Swizzle& swizzle = dstView.swizzle();
337*c8dee2aaSAndroid Build Coastguard Worker fDstTextureSamplerHandle = this->emitSampler(dstTextureProxy->backendFormat(),
338*c8dee2aaSAndroid Build Coastguard Worker GrSamplerState(), swizzle, "DstTextureSampler");
339*c8dee2aaSAndroid Build Coastguard Worker if (!fDstTextureSamplerHandle.isValid()) {
340*c8dee2aaSAndroid Build Coastguard Worker return false;
341*c8dee2aaSAndroid Build Coastguard Worker }
342*c8dee2aaSAndroid Build Coastguard Worker fDstTextureOrigin = dstView.origin();
343*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(dstTextureProxy->textureType() != GrTextureType::kExternal);
344*c8dee2aaSAndroid Build Coastguard Worker
345*c8dee2aaSAndroid Build Coastguard Worker // Declare a _dstColor global variable which samples from the dest-texture sampler at the
346*c8dee2aaSAndroid Build Coastguard Worker // top of the fragment shader.
347*c8dee2aaSAndroid Build Coastguard Worker const char* dstTextureCoordsName;
348*c8dee2aaSAndroid Build Coastguard Worker fUniformHandles.fDstTextureCoordsUni = this->uniformHandler()->addUniform(
349*c8dee2aaSAndroid Build Coastguard Worker /*owner=*/nullptr,
350*c8dee2aaSAndroid Build Coastguard Worker kFragment_GrShaderFlag,
351*c8dee2aaSAndroid Build Coastguard Worker SkSLType::kHalf4,
352*c8dee2aaSAndroid Build Coastguard Worker "DstTextureCoords",
353*c8dee2aaSAndroid Build Coastguard Worker &dstTextureCoordsName);
354*c8dee2aaSAndroid Build Coastguard Worker fFS.codeAppend("// Read color from copy of the destination\n");
355*c8dee2aaSAndroid Build Coastguard Worker if (dstTextureProxy->textureType() == GrTextureType::k2D) {
356*c8dee2aaSAndroid Build Coastguard Worker fFS.codeAppendf("float2 _dstTexCoord = (sk_FragCoord.xy - %s.xy) * %s.zw;\n",
357*c8dee2aaSAndroid Build Coastguard Worker dstTextureCoordsName, dstTextureCoordsName);
358*c8dee2aaSAndroid Build Coastguard Worker if (fDstTextureOrigin == kBottomLeft_GrSurfaceOrigin) {
359*c8dee2aaSAndroid Build Coastguard Worker fFS.codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;\n");
360*c8dee2aaSAndroid Build Coastguard Worker }
361*c8dee2aaSAndroid Build Coastguard Worker } else {
362*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(dstTextureProxy->textureType() == GrTextureType::kRectangle);
363*c8dee2aaSAndroid Build Coastguard Worker fFS.codeAppendf("float2 _dstTexCoord = sk_FragCoord.xy - %s.xy;\n",
364*c8dee2aaSAndroid Build Coastguard Worker dstTextureCoordsName);
365*c8dee2aaSAndroid Build Coastguard Worker if (fDstTextureOrigin == kBottomLeft_GrSurfaceOrigin) {
366*c8dee2aaSAndroid Build Coastguard Worker // When the texture type is kRectangle, instead of a scale stored in the zw of the
367*c8dee2aaSAndroid Build Coastguard Worker // uniform, we store the height in z so we can flip the coord here.
368*c8dee2aaSAndroid Build Coastguard Worker fFS.codeAppendf("_dstTexCoord.y = %s.z - _dstTexCoord.y;\n", dstTextureCoordsName);
369*c8dee2aaSAndroid Build Coastguard Worker }
370*c8dee2aaSAndroid Build Coastguard Worker }
371*c8dee2aaSAndroid Build Coastguard Worker const char* dstColor = fFS.dstColor();
372*c8dee2aaSAndroid Build Coastguard Worker SkString dstColorDecl = SkStringPrintf("half4 %s;", dstColor);
373*c8dee2aaSAndroid Build Coastguard Worker fFS.definitionAppend(dstColorDecl.c_str());
374*c8dee2aaSAndroid Build Coastguard Worker fFS.codeAppendf("%s = ", dstColor);
375*c8dee2aaSAndroid Build Coastguard Worker fFS.appendTextureLookup(fDstTextureSamplerHandle, "_dstTexCoord");
376*c8dee2aaSAndroid Build Coastguard Worker fFS.codeAppend(";\n");
377*c8dee2aaSAndroid Build Coastguard Worker } else if (this->pipeline().usesDstInputAttachment()) {
378*c8dee2aaSAndroid Build Coastguard Worker // Set up an input attachment for the destination texture.
379*c8dee2aaSAndroid Build Coastguard Worker const skgpu::Swizzle& swizzle = dstView.swizzle();
380*c8dee2aaSAndroid Build Coastguard Worker fDstTextureSamplerHandle = this->emitInputSampler(swizzle, "DstTextureInput");
381*c8dee2aaSAndroid Build Coastguard Worker if (!fDstTextureSamplerHandle.isValid()) {
382*c8dee2aaSAndroid Build Coastguard Worker return false;
383*c8dee2aaSAndroid Build Coastguard Worker }
384*c8dee2aaSAndroid Build Coastguard Worker
385*c8dee2aaSAndroid Build Coastguard Worker // Populate the _dstColor variable by loading from the input attachment at the top of the
386*c8dee2aaSAndroid Build Coastguard Worker // fragment shader.
387*c8dee2aaSAndroid Build Coastguard Worker fFS.codeAppend("// Read color from input attachment\n");
388*c8dee2aaSAndroid Build Coastguard Worker const char* dstColor = fFS.dstColor();
389*c8dee2aaSAndroid Build Coastguard Worker SkString dstColorDecl = SkStringPrintf("half4 %s;", dstColor);
390*c8dee2aaSAndroid Build Coastguard Worker fFS.definitionAppend(dstColorDecl.c_str());
391*c8dee2aaSAndroid Build Coastguard Worker fFS.codeAppendf("%s = ", dstColor);
392*c8dee2aaSAndroid Build Coastguard Worker fFS.appendInputLoad(fDstTextureSamplerHandle);
393*c8dee2aaSAndroid Build Coastguard Worker fFS.codeAppend(";\n");
394*c8dee2aaSAndroid Build Coastguard Worker }
395*c8dee2aaSAndroid Build Coastguard Worker
396*c8dee2aaSAndroid Build Coastguard Worker return true;
397*c8dee2aaSAndroid Build Coastguard Worker }
398*c8dee2aaSAndroid Build Coastguard Worker
emitAndInstallXferProc(const SkString & colorIn,const SkString & coverageIn)399*c8dee2aaSAndroid Build Coastguard Worker bool GrGLSLProgramBuilder::emitAndInstallXferProc(const SkString& colorIn,
400*c8dee2aaSAndroid Build Coastguard Worker const SkString& coverageIn) {
401*c8dee2aaSAndroid Build Coastguard Worker // Program builders have a bit of state we need to clear with each effect
402*c8dee2aaSAndroid Build Coastguard Worker this->advanceStage();
403*c8dee2aaSAndroid Build Coastguard Worker
404*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fXPImpl);
405*c8dee2aaSAndroid Build Coastguard Worker const GrXferProcessor& xp = this->pipeline().getXferProcessor();
406*c8dee2aaSAndroid Build Coastguard Worker fXPImpl = xp.makeProgramImpl();
407*c8dee2aaSAndroid Build Coastguard Worker
408*c8dee2aaSAndroid Build Coastguard Worker // Enable dual source secondary output if we have one
409*c8dee2aaSAndroid Build Coastguard Worker if (xp.hasSecondaryOutput()) {
410*c8dee2aaSAndroid Build Coastguard Worker fFS.enableSecondaryOutput();
411*c8dee2aaSAndroid Build Coastguard Worker }
412*c8dee2aaSAndroid Build Coastguard Worker
413*c8dee2aaSAndroid Build Coastguard Worker SkString openBrace;
414*c8dee2aaSAndroid Build Coastguard Worker openBrace.printf("{ // Xfer Processor: %s\n", xp.name());
415*c8dee2aaSAndroid Build Coastguard Worker fFS.codeAppend(openBrace.c_str());
416*c8dee2aaSAndroid Build Coastguard Worker
417*c8dee2aaSAndroid Build Coastguard Worker SkString finalInColor = colorIn.size() ? colorIn : SkString("float4(1)");
418*c8dee2aaSAndroid Build Coastguard Worker
419*c8dee2aaSAndroid Build Coastguard Worker GrXferProcessor::ProgramImpl::EmitArgs args(
420*c8dee2aaSAndroid Build Coastguard Worker &fFS,
421*c8dee2aaSAndroid Build Coastguard Worker this->uniformHandler(),
422*c8dee2aaSAndroid Build Coastguard Worker this->shaderCaps(),
423*c8dee2aaSAndroid Build Coastguard Worker xp,
424*c8dee2aaSAndroid Build Coastguard Worker finalInColor.c_str(),
425*c8dee2aaSAndroid Build Coastguard Worker coverageIn.size() ? coverageIn.c_str() : "float4(1)",
426*c8dee2aaSAndroid Build Coastguard Worker fFS.getPrimaryColorOutputName(),
427*c8dee2aaSAndroid Build Coastguard Worker fFS.getSecondaryColorOutputName(),
428*c8dee2aaSAndroid Build Coastguard Worker fDstTextureSamplerHandle,
429*c8dee2aaSAndroid Build Coastguard Worker fDstTextureOrigin,
430*c8dee2aaSAndroid Build Coastguard Worker this->pipeline().writeSwizzle());
431*c8dee2aaSAndroid Build Coastguard Worker fXPImpl->emitCode(args);
432*c8dee2aaSAndroid Build Coastguard Worker
433*c8dee2aaSAndroid Build Coastguard Worker // We have to check that effects and the code they emit are consistent, ie if an effect
434*c8dee2aaSAndroid Build Coastguard Worker // asks for dst color, then the emit code needs to follow suit
435*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(verify(xp);)
436*c8dee2aaSAndroid Build Coastguard Worker fFS.codeAppend("}");
437*c8dee2aaSAndroid Build Coastguard Worker return true;
438*c8dee2aaSAndroid Build Coastguard Worker }
439*c8dee2aaSAndroid Build Coastguard Worker
emitSampler(const GrBackendFormat & backendFormat,GrSamplerState state,const skgpu::Swizzle & swizzle,const char * name)440*c8dee2aaSAndroid Build Coastguard Worker GrGLSLProgramBuilder::SamplerHandle GrGLSLProgramBuilder::emitSampler(
441*c8dee2aaSAndroid Build Coastguard Worker const GrBackendFormat& backendFormat, GrSamplerState state, const skgpu::Swizzle& swizzle,
442*c8dee2aaSAndroid Build Coastguard Worker const char* name) {
443*c8dee2aaSAndroid Build Coastguard Worker ++fNumFragmentSamplers;
444*c8dee2aaSAndroid Build Coastguard Worker return this->uniformHandler()->addSampler(backendFormat, state, swizzle, name,
445*c8dee2aaSAndroid Build Coastguard Worker this->shaderCaps());
446*c8dee2aaSAndroid Build Coastguard Worker }
447*c8dee2aaSAndroid Build Coastguard Worker
emitInputSampler(const skgpu::Swizzle & swizzle,const char * name)448*c8dee2aaSAndroid Build Coastguard Worker GrGLSLProgramBuilder::SamplerHandle GrGLSLProgramBuilder::emitInputSampler(
449*c8dee2aaSAndroid Build Coastguard Worker const skgpu::Swizzle& swizzle, const char* name) {
450*c8dee2aaSAndroid Build Coastguard Worker return this->uniformHandler()->addInputSampler(swizzle, name);
451*c8dee2aaSAndroid Build Coastguard Worker }
452*c8dee2aaSAndroid Build Coastguard Worker
checkSamplerCounts()453*c8dee2aaSAndroid Build Coastguard Worker bool GrGLSLProgramBuilder::checkSamplerCounts() {
454*c8dee2aaSAndroid Build Coastguard Worker const GrShaderCaps& shaderCaps = *this->shaderCaps();
455*c8dee2aaSAndroid Build Coastguard Worker if (fNumFragmentSamplers > shaderCaps.fMaxFragmentSamplers) {
456*c8dee2aaSAndroid Build Coastguard Worker GrCapsDebugf(this->caps(), "Program would use too many fragment samplers\n");
457*c8dee2aaSAndroid Build Coastguard Worker return false;
458*c8dee2aaSAndroid Build Coastguard Worker }
459*c8dee2aaSAndroid Build Coastguard Worker return true;
460*c8dee2aaSAndroid Build Coastguard Worker }
461*c8dee2aaSAndroid Build Coastguard Worker
462*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
verify(const GrGeometryProcessor & geomProc)463*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLProgramBuilder::verify(const GrGeometryProcessor& geomProc) {
464*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fFS.fHasReadDstColorThisStage_DebugOnly);
465*c8dee2aaSAndroid Build Coastguard Worker }
466*c8dee2aaSAndroid Build Coastguard Worker
verify(const GrFragmentProcessor & fp)467*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLProgramBuilder::verify(const GrFragmentProcessor& fp) {
468*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fp.willReadDstColor() == fFS.fHasReadDstColorThisStage_DebugOnly);
469*c8dee2aaSAndroid Build Coastguard Worker }
470*c8dee2aaSAndroid Build Coastguard Worker
verify(const GrXferProcessor & xp)471*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLProgramBuilder::verify(const GrXferProcessor& xp) {
472*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(xp.willReadDstColor() == fFS.fHasReadDstColorThisStage_DebugOnly);
473*c8dee2aaSAndroid Build Coastguard Worker }
474*c8dee2aaSAndroid Build Coastguard Worker #endif
475*c8dee2aaSAndroid Build Coastguard Worker
getMangleSuffix() const476*c8dee2aaSAndroid Build Coastguard Worker SkString GrGLSLProgramBuilder::getMangleSuffix() const {
477*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fStageIndex >= 0);
478*c8dee2aaSAndroid Build Coastguard Worker SkString suffix;
479*c8dee2aaSAndroid Build Coastguard Worker suffix.printf("_S%d", fStageIndex);
480*c8dee2aaSAndroid Build Coastguard Worker for (auto c : fSubstageIndices) {
481*c8dee2aaSAndroid Build Coastguard Worker suffix.appendf("_c%d", c);
482*c8dee2aaSAndroid Build Coastguard Worker }
483*c8dee2aaSAndroid Build Coastguard Worker return suffix;
484*c8dee2aaSAndroid Build Coastguard Worker }
485*c8dee2aaSAndroid Build Coastguard Worker
nameVariable(char prefix,const char * name,bool mangle)486*c8dee2aaSAndroid Build Coastguard Worker SkString GrGLSLProgramBuilder::nameVariable(char prefix, const char* name, bool mangle) {
487*c8dee2aaSAndroid Build Coastguard Worker SkString out;
488*c8dee2aaSAndroid Build Coastguard Worker if ('\0' == prefix) {
489*c8dee2aaSAndroid Build Coastguard Worker out = name;
490*c8dee2aaSAndroid Build Coastguard Worker } else {
491*c8dee2aaSAndroid Build Coastguard Worker out.printf("%c%s", prefix, name);
492*c8dee2aaSAndroid Build Coastguard Worker }
493*c8dee2aaSAndroid Build Coastguard Worker if (mangle) {
494*c8dee2aaSAndroid Build Coastguard Worker SkString suffix = this->getMangleSuffix();
495*c8dee2aaSAndroid Build Coastguard Worker // Names containing "__" are reserved; add "x" if needed to avoid consecutive underscores.
496*c8dee2aaSAndroid Build Coastguard Worker const char *underscoreSplitter = out.endsWith('_') ? "x" : "";
497*c8dee2aaSAndroid Build Coastguard Worker out.appendf("%s%s", underscoreSplitter, suffix.c_str());
498*c8dee2aaSAndroid Build Coastguard Worker }
499*c8dee2aaSAndroid Build Coastguard Worker return out;
500*c8dee2aaSAndroid Build Coastguard Worker }
501*c8dee2aaSAndroid Build Coastguard Worker
nameExpression(SkString * output,const char * baseName)502*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLProgramBuilder::nameExpression(SkString* output, const char* baseName) {
503*c8dee2aaSAndroid Build Coastguard Worker // Name a variable to hold stage result. If we already have a valid output name, use that as-is;
504*c8dee2aaSAndroid Build Coastguard Worker // otherwise, create a new mangled one.
505*c8dee2aaSAndroid Build Coastguard Worker if (output->isEmpty()) {
506*c8dee2aaSAndroid Build Coastguard Worker *output = this->nameVariable(/*prefix=*/'\0', baseName);
507*c8dee2aaSAndroid Build Coastguard Worker }
508*c8dee2aaSAndroid Build Coastguard Worker }
509*c8dee2aaSAndroid Build Coastguard Worker
appendUniformDecls(GrShaderFlags visibility,SkString * out) const510*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLProgramBuilder::appendUniformDecls(GrShaderFlags visibility, SkString* out) const {
511*c8dee2aaSAndroid Build Coastguard Worker this->uniformHandler()->appendUniformDecls(visibility, out);
512*c8dee2aaSAndroid Build Coastguard Worker }
513*c8dee2aaSAndroid Build Coastguard Worker
addRTFlipUniform(const char * name)514*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLProgramBuilder::addRTFlipUniform(const char* name) {
515*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fUniformHandles.fRTFlipUni.isValid());
516*c8dee2aaSAndroid Build Coastguard Worker GrGLSLUniformHandler* uniformHandler = this->uniformHandler();
517*c8dee2aaSAndroid Build Coastguard Worker fUniformHandles.fRTFlipUni =
518*c8dee2aaSAndroid Build Coastguard Worker uniformHandler->internalAddUniformArray(nullptr,
519*c8dee2aaSAndroid Build Coastguard Worker kFragment_GrShaderFlag,
520*c8dee2aaSAndroid Build Coastguard Worker SkSLType::kFloat2,
521*c8dee2aaSAndroid Build Coastguard Worker name,
522*c8dee2aaSAndroid Build Coastguard Worker false,
523*c8dee2aaSAndroid Build Coastguard Worker 0,
524*c8dee2aaSAndroid Build Coastguard Worker nullptr);
525*c8dee2aaSAndroid Build Coastguard Worker }
526*c8dee2aaSAndroid Build Coastguard Worker
fragmentProcessorHasCoordsParam(const GrFragmentProcessor * fp) const527*c8dee2aaSAndroid Build Coastguard Worker bool GrGLSLProgramBuilder::fragmentProcessorHasCoordsParam(const GrFragmentProcessor* fp) const {
528*c8dee2aaSAndroid Build Coastguard Worker auto iter = fFPCoordsMap.find(fp);
529*c8dee2aaSAndroid Build Coastguard Worker return (iter != fFPCoordsMap.end()) ? iter->second.hasCoordsParam
530*c8dee2aaSAndroid Build Coastguard Worker : fp->usesSampleCoords();
531*c8dee2aaSAndroid Build Coastguard Worker }
532*c8dee2aaSAndroid Build Coastguard Worker
finalizeShaders()533*c8dee2aaSAndroid Build Coastguard Worker void GrGLSLProgramBuilder::finalizeShaders() {
534*c8dee2aaSAndroid Build Coastguard Worker this->varyingHandler()->finalize();
535*c8dee2aaSAndroid Build Coastguard Worker fVS.finalize(kVertex_GrShaderFlag);
536*c8dee2aaSAndroid Build Coastguard Worker fFS.finalize(kFragment_GrShaderFlag);
537*c8dee2aaSAndroid Build Coastguard Worker }
538