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