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