1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2014 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/GrGeometryProcessor.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "src/core/SkMatrixPriv.h" 11cb93a386Sopenharmony_ci#include "src/gpu/GrPipeline.h" 12cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" 13cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLProgramBuilder.h" 14cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLUniformHandler.h" 15cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLVarying.h" 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_ci#include <queue> 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_ciGrGeometryProcessor::GrGeometryProcessor(ClassID classID) : GrProcessor(classID) {} 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_ciconst GrGeometryProcessor::TextureSampler& GrGeometryProcessor::textureSampler(int i) const { 22cb93a386Sopenharmony_ci SkASSERT(i >= 0 && i < this->numTextureSamplers()); 23cb93a386Sopenharmony_ci return this->onTextureSampler(i); 24cb93a386Sopenharmony_ci} 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_ciuint32_t GrGeometryProcessor::ComputeCoordTransformsKey(const GrFragmentProcessor& fp) { 27cb93a386Sopenharmony_ci // This is highly coupled with the code in ProgramImpl::collectTransforms(). 28cb93a386Sopenharmony_ci uint32_t key = static_cast<uint32_t>(fp.sampleUsage().kind()) << 1; 29cb93a386Sopenharmony_ci // This needs to be updated if GP starts specializing varyings on additional matrix types. 30cb93a386Sopenharmony_ci if (fp.sampleUsage().hasPerspective()) { 31cb93a386Sopenharmony_ci key |= 0b1; 32cb93a386Sopenharmony_ci } 33cb93a386Sopenharmony_ci return key; 34cb93a386Sopenharmony_ci} 35cb93a386Sopenharmony_ci 36cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////////////////////////// 37cb93a386Sopenharmony_ci 38cb93a386Sopenharmony_cistatic inline GrSamplerState::Filter clamp_filter(GrTextureType type, 39cb93a386Sopenharmony_ci GrSamplerState::Filter requestedFilter) { 40cb93a386Sopenharmony_ci if (GrTextureTypeHasRestrictedSampling(type)) { 41cb93a386Sopenharmony_ci return std::min(requestedFilter, GrSamplerState::Filter::kLinear); 42cb93a386Sopenharmony_ci } 43cb93a386Sopenharmony_ci return requestedFilter; 44cb93a386Sopenharmony_ci} 45cb93a386Sopenharmony_ci 46cb93a386Sopenharmony_ciGrGeometryProcessor::TextureSampler::TextureSampler(GrSamplerState samplerState, 47cb93a386Sopenharmony_ci const GrBackendFormat& backendFormat, 48cb93a386Sopenharmony_ci const GrSwizzle& swizzle) { 49cb93a386Sopenharmony_ci this->reset(samplerState, backendFormat, swizzle); 50cb93a386Sopenharmony_ci} 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_civoid GrGeometryProcessor::TextureSampler::reset(GrSamplerState samplerState, 53cb93a386Sopenharmony_ci const GrBackendFormat& backendFormat, 54cb93a386Sopenharmony_ci const GrSwizzle& swizzle) { 55cb93a386Sopenharmony_ci fSamplerState = samplerState; 56cb93a386Sopenharmony_ci fSamplerState.setFilterMode(clamp_filter(backendFormat.textureType(), samplerState.filter())); 57cb93a386Sopenharmony_ci fBackendFormat = backendFormat; 58cb93a386Sopenharmony_ci fSwizzle = swizzle; 59cb93a386Sopenharmony_ci fIsInitialized = true; 60cb93a386Sopenharmony_ci} 61cb93a386Sopenharmony_ci 62cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////// 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_ciusing ProgramImpl = GrGeometryProcessor::ProgramImpl; 65cb93a386Sopenharmony_ci 66cb93a386Sopenharmony_ciProgramImpl::FPCoordsMap ProgramImpl::emitCode(EmitArgs& args, const GrPipeline& pipeline) { 67cb93a386Sopenharmony_ci GrGPArgs gpArgs; 68cb93a386Sopenharmony_ci this->onEmitCode(args, &gpArgs); 69cb93a386Sopenharmony_ci 70cb93a386Sopenharmony_ci GrShaderVar positionVar = gpArgs.fPositionVar; 71cb93a386Sopenharmony_ci // skia:12198 72cb93a386Sopenharmony_ci if (args.fGeomProc.willUseTessellationShaders()) { 73cb93a386Sopenharmony_ci positionVar = {}; 74cb93a386Sopenharmony_ci } 75cb93a386Sopenharmony_ci FPCoordsMap transformMap = this->collectTransforms(args.fVertBuilder, 76cb93a386Sopenharmony_ci args.fVaryingHandler, 77cb93a386Sopenharmony_ci args.fUniformHandler, 78cb93a386Sopenharmony_ci gpArgs.fLocalCoordVar, 79cb93a386Sopenharmony_ci positionVar, 80cb93a386Sopenharmony_ci pipeline); 81cb93a386Sopenharmony_ci 82cb93a386Sopenharmony_ci if (args.fGeomProc.willUseTessellationShaders()) { 83cb93a386Sopenharmony_ci // Tessellation shaders are temporarily responsible for integrating their own code strings 84cb93a386Sopenharmony_ci // while we work out full support. 85cb93a386Sopenharmony_ci return transformMap; 86cb93a386Sopenharmony_ci } 87cb93a386Sopenharmony_ci 88cb93a386Sopenharmony_ci GrGLSLVertexBuilder* vBuilder = args.fVertBuilder; 89cb93a386Sopenharmony_ci // Emit the vertex position to the hardware in the normalized window coordinates it expects. 90cb93a386Sopenharmony_ci SkASSERT(kFloat2_GrSLType == gpArgs.fPositionVar.getType() || 91cb93a386Sopenharmony_ci kFloat3_GrSLType == gpArgs.fPositionVar.getType()); 92cb93a386Sopenharmony_ci vBuilder->emitNormalizedSkPosition(gpArgs.fPositionVar.c_str(), 93cb93a386Sopenharmony_ci gpArgs.fPositionVar.getType()); 94cb93a386Sopenharmony_ci if (kFloat2_GrSLType == gpArgs.fPositionVar.getType()) { 95cb93a386Sopenharmony_ci args.fVaryingHandler->setNoPerspective(); 96cb93a386Sopenharmony_ci } 97cb93a386Sopenharmony_ci return transformMap; 98cb93a386Sopenharmony_ci} 99cb93a386Sopenharmony_ci 100cb93a386Sopenharmony_ciProgramImpl::FPCoordsMap ProgramImpl::collectTransforms(GrGLSLVertexBuilder* vb, 101cb93a386Sopenharmony_ci GrGLSLVaryingHandler* varyingHandler, 102cb93a386Sopenharmony_ci GrGLSLUniformHandler* uniformHandler, 103cb93a386Sopenharmony_ci const GrShaderVar& localCoordsVar, 104cb93a386Sopenharmony_ci const GrShaderVar& positionVar, 105cb93a386Sopenharmony_ci const GrPipeline& pipeline) { 106cb93a386Sopenharmony_ci SkASSERT(localCoordsVar.getType() == kFloat2_GrSLType || 107cb93a386Sopenharmony_ci localCoordsVar.getType() == kFloat3_GrSLType || 108cb93a386Sopenharmony_ci localCoordsVar.getType() == kVoid_GrSLType); 109cb93a386Sopenharmony_ci SkASSERT(positionVar.getType() == kFloat2_GrSLType || 110cb93a386Sopenharmony_ci positionVar.getType() == kFloat3_GrSLType || 111cb93a386Sopenharmony_ci positionVar.getType() == kVoid_GrSLType); 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ci enum class BaseCoord { kNone, kLocal, kPosition }; 114cb93a386Sopenharmony_ci 115cb93a386Sopenharmony_ci auto baseLocalCoordFSVar = [&, baseLocalCoord = GrGLSLVarying()]() mutable { 116cb93a386Sopenharmony_ci SkASSERT(GrSLTypeIsFloatType(localCoordsVar.getType())); 117cb93a386Sopenharmony_ci if (baseLocalCoord.type() == kVoid_GrSLType) { 118cb93a386Sopenharmony_ci // Initialize to the GP provided coordinate 119cb93a386Sopenharmony_ci baseLocalCoord = GrGLSLVarying(localCoordsVar.getType()); 120cb93a386Sopenharmony_ci varyingHandler->addVarying("LocalCoord", &baseLocalCoord); 121cb93a386Sopenharmony_ci vb->codeAppendf("%s = %s;\n", baseLocalCoord.vsOut(), localCoordsVar.getName().c_str()); 122cb93a386Sopenharmony_ci } 123cb93a386Sopenharmony_ci return baseLocalCoord.fsInVar(); 124cb93a386Sopenharmony_ci }; 125cb93a386Sopenharmony_ci 126cb93a386Sopenharmony_ci bool canUsePosition = positionVar.getType() != kVoid_GrSLType; 127cb93a386Sopenharmony_ci 128cb93a386Sopenharmony_ci FPCoordsMap result; 129cb93a386Sopenharmony_ci // Performs a pre-order traversal of FP hierarchy rooted at fp and identifies FPs that are 130cb93a386Sopenharmony_ci // sampled with a series of matrices applied to local coords. For each such FP a varying is 131cb93a386Sopenharmony_ci // added to the varying handler and added to 'result'. 132cb93a386Sopenharmony_ci auto liftTransforms = [&, traversalIndex = 0]( 133cb93a386Sopenharmony_ci auto& self, 134cb93a386Sopenharmony_ci const GrFragmentProcessor& fp, 135cb93a386Sopenharmony_ci bool hasPerspective, 136cb93a386Sopenharmony_ci const GrFragmentProcessor* lastMatrixFP = nullptr, 137cb93a386Sopenharmony_ci int lastMatrixTraversalIndex = -1, 138cb93a386Sopenharmony_ci BaseCoord baseCoord = BaseCoord::kLocal) mutable -> void { 139cb93a386Sopenharmony_ci ++traversalIndex; 140cb93a386Sopenharmony_ci switch (fp.sampleUsage().kind()) { 141cb93a386Sopenharmony_ci case SkSL::SampleUsage::Kind::kNone: 142cb93a386Sopenharmony_ci // This should only happen at the root. Otherwise how did this FP get added? 143cb93a386Sopenharmony_ci SkASSERT(!fp.parent()); 144cb93a386Sopenharmony_ci break; 145cb93a386Sopenharmony_ci case SkSL::SampleUsage::Kind::kPassThrough: 146cb93a386Sopenharmony_ci break; 147cb93a386Sopenharmony_ci case SkSL::SampleUsage::Kind::kUniformMatrix: 148cb93a386Sopenharmony_ci // Update tracking of last matrix and matrix props. 149cb93a386Sopenharmony_ci hasPerspective |= fp.sampleUsage().hasPerspective(); 150cb93a386Sopenharmony_ci lastMatrixFP = &fp; 151cb93a386Sopenharmony_ci lastMatrixTraversalIndex = traversalIndex; 152cb93a386Sopenharmony_ci break; 153cb93a386Sopenharmony_ci case SkSL::SampleUsage::Kind::kFragCoord: 154cb93a386Sopenharmony_ci hasPerspective = positionVar.getType() == kFloat3_GrSLType; 155cb93a386Sopenharmony_ci lastMatrixFP = nullptr; 156cb93a386Sopenharmony_ci lastMatrixTraversalIndex = -1; 157cb93a386Sopenharmony_ci baseCoord = BaseCoord::kPosition; 158cb93a386Sopenharmony_ci break; 159cb93a386Sopenharmony_ci case SkSL::SampleUsage::Kind::kExplicit: 160cb93a386Sopenharmony_ci baseCoord = BaseCoord::kNone; 161cb93a386Sopenharmony_ci break; 162cb93a386Sopenharmony_ci } 163cb93a386Sopenharmony_ci 164cb93a386Sopenharmony_ci auto& [varyingFSVar, hasCoordsParam] = result[&fp]; 165cb93a386Sopenharmony_ci hasCoordsParam = fp.usesSampleCoordsDirectly(); 166cb93a386Sopenharmony_ci 167cb93a386Sopenharmony_ci // We add a varying if we're in a chain of matrices multiplied by local or device coords. 168cb93a386Sopenharmony_ci // If the coord is the untransformed local coord we add a varying. We don't if it is 169cb93a386Sopenharmony_ci // untransformed device coords since it doesn't save us anything over "sk_FragCoord.xy". Of 170cb93a386Sopenharmony_ci // course, if the FP doesn't directly use its coords then we don't add a varying. 171cb93a386Sopenharmony_ci if (fp.usesSampleCoordsDirectly() && 172cb93a386Sopenharmony_ci (baseCoord == BaseCoord::kLocal || 173cb93a386Sopenharmony_ci (baseCoord == BaseCoord::kPosition && lastMatrixFP && canUsePosition))) { 174cb93a386Sopenharmony_ci // Associate the varying with the highest possible node in the FP tree that shares the 175cb93a386Sopenharmony_ci // same coordinates so that multiple FPs in a subtree can share. If there are no matrix 176cb93a386Sopenharmony_ci // sample nodes on the way up the tree then directly use the local coord. 177cb93a386Sopenharmony_ci if (!lastMatrixFP) { 178cb93a386Sopenharmony_ci varyingFSVar = baseLocalCoordFSVar(); 179cb93a386Sopenharmony_ci } else { 180cb93a386Sopenharmony_ci // If there is an already a varying that incorporates all matrices from the root to 181cb93a386Sopenharmony_ci // lastMatrixFP just use it. Otherwise, we add it. 182cb93a386Sopenharmony_ci auto& [varying, inputCoords, varyingIdx] = fTransformVaryingsMap[lastMatrixFP]; 183cb93a386Sopenharmony_ci if (varying.type() == kVoid_GrSLType) { 184cb93a386Sopenharmony_ci varying = GrGLSLVarying(hasPerspective ? kFloat3_GrSLType : kFloat2_GrSLType); 185cb93a386Sopenharmony_ci SkString strVaryingName = SkStringPrintf("TransformedCoords_%d", 186cb93a386Sopenharmony_ci lastMatrixTraversalIndex); 187cb93a386Sopenharmony_ci varyingHandler->addVarying(strVaryingName.c_str(), &varying); 188cb93a386Sopenharmony_ci inputCoords = baseCoord == BaseCoord::kLocal ? localCoordsVar : positionVar; 189cb93a386Sopenharmony_ci varyingIdx = lastMatrixTraversalIndex; 190cb93a386Sopenharmony_ci } 191cb93a386Sopenharmony_ci SkASSERT(varyingIdx == lastMatrixTraversalIndex); 192cb93a386Sopenharmony_ci // The FP will use the varying in the fragment shader as its coords. 193cb93a386Sopenharmony_ci varyingFSVar = varying.fsInVar(); 194cb93a386Sopenharmony_ci } 195cb93a386Sopenharmony_ci hasCoordsParam = false; 196cb93a386Sopenharmony_ci } 197cb93a386Sopenharmony_ci 198cb93a386Sopenharmony_ci for (int c = 0; c < fp.numChildProcessors(); ++c) { 199cb93a386Sopenharmony_ci if (auto* child = fp.childProcessor(c)) { 200cb93a386Sopenharmony_ci self(self, 201cb93a386Sopenharmony_ci *child, 202cb93a386Sopenharmony_ci hasPerspective, 203cb93a386Sopenharmony_ci lastMatrixFP, 204cb93a386Sopenharmony_ci lastMatrixTraversalIndex, 205cb93a386Sopenharmony_ci baseCoord); 206cb93a386Sopenharmony_ci // If we have a varying then we never need a param. Otherwise, if one of our 207cb93a386Sopenharmony_ci // children takes a non-explicit coord then we'll need our coord. 208cb93a386Sopenharmony_ci hasCoordsParam |= varyingFSVar.getType() == kVoid_GrSLType && 209cb93a386Sopenharmony_ci !child->sampleUsage().isExplicit() && 210cb93a386Sopenharmony_ci !child->sampleUsage().isFragCoord() && 211cb93a386Sopenharmony_ci result[child].hasCoordsParam; 212cb93a386Sopenharmony_ci } 213cb93a386Sopenharmony_ci } 214cb93a386Sopenharmony_ci }; 215cb93a386Sopenharmony_ci 216cb93a386Sopenharmony_ci bool hasPerspective = GrSLTypeVecLength(localCoordsVar.getType()) == 3; 217cb93a386Sopenharmony_ci for (int i = 0; i < pipeline.numFragmentProcessors(); ++i) { 218cb93a386Sopenharmony_ci liftTransforms(liftTransforms, pipeline.getFragmentProcessor(i), hasPerspective); 219cb93a386Sopenharmony_ci } 220cb93a386Sopenharmony_ci return result; 221cb93a386Sopenharmony_ci} 222cb93a386Sopenharmony_ci 223cb93a386Sopenharmony_civoid ProgramImpl::emitTransformCode(GrGLSLVertexBuilder* vb, GrGLSLUniformHandler* uniformHandler) { 224cb93a386Sopenharmony_ci // Because descendant varyings may be computed using the varyings of ancestor FPs we make 225cb93a386Sopenharmony_ci // sure to visit the varyings according to FP pre-order traversal by dumping them into a 226cb93a386Sopenharmony_ci // priority queue. 227cb93a386Sopenharmony_ci using FPAndInfo = std::tuple<const GrFragmentProcessor*, TransformInfo>; 228cb93a386Sopenharmony_ci auto compare = [](const FPAndInfo& a, const FPAndInfo& b) { 229cb93a386Sopenharmony_ci return std::get<1>(a).traversalOrder > std::get<1>(b).traversalOrder; 230cb93a386Sopenharmony_ci }; 231cb93a386Sopenharmony_ci std::priority_queue<FPAndInfo, std::vector<FPAndInfo>, decltype(compare)> pq(compare); 232cb93a386Sopenharmony_ci std::for_each(fTransformVaryingsMap.begin(), fTransformVaryingsMap.end(), [&pq](auto entry) { 233cb93a386Sopenharmony_ci pq.push(entry); 234cb93a386Sopenharmony_ci }); 235cb93a386Sopenharmony_ci for (; !pq.empty(); pq.pop()) { 236cb93a386Sopenharmony_ci const auto& [fp, info] = pq.top(); 237cb93a386Sopenharmony_ci // If we recorded a transform info, its sample matrix must be uniform 238cb93a386Sopenharmony_ci SkASSERT(fp->sampleUsage().isUniformMatrix()); 239cb93a386Sopenharmony_ci GrShaderVar uniform = uniformHandler->liftUniformToVertexShader( 240cb93a386Sopenharmony_ci *fp->parent(), SkString(SkSL::SampleUsage::MatrixUniformName())); 241cb93a386Sopenharmony_ci // Start with this matrix and accumulate additional matrices as we walk up the FP tree 242cb93a386Sopenharmony_ci // to either the base coords or an ancestor FP that has an associated varying. 243cb93a386Sopenharmony_ci SkString transformExpression = uniform.getName(); 244cb93a386Sopenharmony_ci 245cb93a386Sopenharmony_ci // If we hit an ancestor with a varying on our walk up then save off the varying as the 246cb93a386Sopenharmony_ci // input to our accumulated transformExpression. Start off assuming we'll reach the root. 247cb93a386Sopenharmony_ci GrShaderVar inputCoords = info.inputCoords; 248cb93a386Sopenharmony_ci 249cb93a386Sopenharmony_ci for (const auto* base = fp->parent(); base; base = base->parent()) { 250cb93a386Sopenharmony_ci if (auto iter = fTransformVaryingsMap.find(base); iter != fTransformVaryingsMap.end()) { 251cb93a386Sopenharmony_ci // Can stop here, as this varying already holds all transforms from higher FPs 252cb93a386Sopenharmony_ci // We'll apply the residual transformExpression we've accumulated up from our 253cb93a386Sopenharmony_ci // starting FP to this varying. 254cb93a386Sopenharmony_ci inputCoords = iter->second.varying.vsOutVar(); 255cb93a386Sopenharmony_ci break; 256cb93a386Sopenharmony_ci } else if (base->sampleUsage().isUniformMatrix()) { 257cb93a386Sopenharmony_ci // Accumulate any matrices along the path to either the original local/device coords 258cb93a386Sopenharmony_ci // or a parent varying. Getting here means this FP was sampled with a uniform matrix 259cb93a386Sopenharmony_ci // but all uses of coords below here in the FP hierarchy are beneath additional 260cb93a386Sopenharmony_ci // matrix samples and thus this node wasn't assigned a varying. 261cb93a386Sopenharmony_ci GrShaderVar parentUniform = uniformHandler->liftUniformToVertexShader( 262cb93a386Sopenharmony_ci *base->parent(), SkString(SkSL::SampleUsage::MatrixUniformName())); 263cb93a386Sopenharmony_ci transformExpression.appendf(" * %s", parentUniform.getName().c_str()); 264cb93a386Sopenharmony_ci } else if (base->sampleUsage().isFragCoord()) { 265cb93a386Sopenharmony_ci // Our chain of matrices starts here and is based on the device space position. 266cb93a386Sopenharmony_ci break; 267cb93a386Sopenharmony_ci } else { 268cb93a386Sopenharmony_ci // This intermediate FP is just a pass through and doesn't need to be built 269cb93a386Sopenharmony_ci // in to the expression, but we must visit its parents in case they add transforms. 270cb93a386Sopenharmony_ci SkASSERT(base->sampleUsage().isPassThrough() || !base->sampleUsage().isSampled()); 271cb93a386Sopenharmony_ci } 272cb93a386Sopenharmony_ci } 273cb93a386Sopenharmony_ci 274cb93a386Sopenharmony_ci SkString inputStr; 275cb93a386Sopenharmony_ci if (inputCoords.getType() == kFloat2_GrSLType) { 276cb93a386Sopenharmony_ci inputStr = SkStringPrintf("%s.xy1", inputCoords.getName().c_str()); 277cb93a386Sopenharmony_ci } else { 278cb93a386Sopenharmony_ci SkASSERT(inputCoords.getType() == kFloat3_GrSLType); 279cb93a386Sopenharmony_ci inputStr = inputCoords.getName(); 280cb93a386Sopenharmony_ci } 281cb93a386Sopenharmony_ci 282cb93a386Sopenharmony_ci vb->codeAppend("{\n"); 283cb93a386Sopenharmony_ci if (info.varying.type() == kFloat2_GrSLType) { 284cb93a386Sopenharmony_ci if (vb->getProgramBuilder()->shaderCaps()->nonsquareMatrixSupport()) { 285cb93a386Sopenharmony_ci vb->codeAppendf("%s = float3x2(%s) * %s", 286cb93a386Sopenharmony_ci info.varying.vsOut(), 287cb93a386Sopenharmony_ci transformExpression.c_str(), 288cb93a386Sopenharmony_ci inputStr.c_str()); 289cb93a386Sopenharmony_ci } else { 290cb93a386Sopenharmony_ci vb->codeAppendf("%s = (%s * %s).xy", 291cb93a386Sopenharmony_ci info.varying.vsOut(), 292cb93a386Sopenharmony_ci transformExpression.c_str(), 293cb93a386Sopenharmony_ci inputStr.c_str()); 294cb93a386Sopenharmony_ci } 295cb93a386Sopenharmony_ci } else { 296cb93a386Sopenharmony_ci SkASSERT(info.varying.type() == kFloat3_GrSLType); 297cb93a386Sopenharmony_ci vb->codeAppendf("%s = %s * %s", 298cb93a386Sopenharmony_ci info.varying.vsOut(), 299cb93a386Sopenharmony_ci transformExpression.c_str(), 300cb93a386Sopenharmony_ci inputStr.c_str()); 301cb93a386Sopenharmony_ci } 302cb93a386Sopenharmony_ci vb->codeAppend(";\n"); 303cb93a386Sopenharmony_ci vb->codeAppend("}\n"); 304cb93a386Sopenharmony_ci } 305cb93a386Sopenharmony_ci // We don't need this map anymore. 306cb93a386Sopenharmony_ci fTransformVaryingsMap.clear(); 307cb93a386Sopenharmony_ci} 308cb93a386Sopenharmony_ci 309cb93a386Sopenharmony_civoid ProgramImpl::setupUniformColor(GrGLSLFPFragmentBuilder* fragBuilder, 310cb93a386Sopenharmony_ci GrGLSLUniformHandler* uniformHandler, 311cb93a386Sopenharmony_ci const char* outputName, 312cb93a386Sopenharmony_ci UniformHandle* colorUniform) { 313cb93a386Sopenharmony_ci SkASSERT(colorUniform); 314cb93a386Sopenharmony_ci const char* stagedLocalVarName; 315cb93a386Sopenharmony_ci *colorUniform = uniformHandler->addUniform(nullptr, 316cb93a386Sopenharmony_ci kFragment_GrShaderFlag, 317cb93a386Sopenharmony_ci kHalf4_GrSLType, 318cb93a386Sopenharmony_ci "Color", 319cb93a386Sopenharmony_ci &stagedLocalVarName); 320cb93a386Sopenharmony_ci fragBuilder->codeAppendf("%s = %s;", outputName, stagedLocalVarName); 321cb93a386Sopenharmony_ci if (fragBuilder->getProgramBuilder()->shaderCaps()->mustObfuscateUniformColor()) { 322cb93a386Sopenharmony_ci fragBuilder->codeAppendf("%s = max(%s, half4(0));", outputName, outputName); 323cb93a386Sopenharmony_ci } 324cb93a386Sopenharmony_ci} 325cb93a386Sopenharmony_ci 326cb93a386Sopenharmony_civoid ProgramImpl::SetTransform(const GrGLSLProgramDataManager& pdman, 327cb93a386Sopenharmony_ci const GrShaderCaps& shaderCaps, 328cb93a386Sopenharmony_ci const UniformHandle& uniform, 329cb93a386Sopenharmony_ci const SkMatrix& matrix, 330cb93a386Sopenharmony_ci SkMatrix* state) { 331cb93a386Sopenharmony_ci if (!uniform.isValid() || (state && SkMatrixPriv::CheapEqual(*state, matrix))) { 332cb93a386Sopenharmony_ci // No update needed 333cb93a386Sopenharmony_ci return; 334cb93a386Sopenharmony_ci } 335cb93a386Sopenharmony_ci if (state) { 336cb93a386Sopenharmony_ci *state = matrix; 337cb93a386Sopenharmony_ci } 338cb93a386Sopenharmony_ci if (matrix.isScaleTranslate() && !shaderCaps.reducedShaderMode()) { 339cb93a386Sopenharmony_ci // ComputeMatrixKey and writeX() assume the uniform is a float4 (can't assert since nothing 340cb93a386Sopenharmony_ci // is exposed on a handle, but should be caught lower down). 341cb93a386Sopenharmony_ci float values[4] = {matrix.getScaleX(), matrix.getTranslateX(), 342cb93a386Sopenharmony_ci matrix.getScaleY(), matrix.getTranslateY()}; 343cb93a386Sopenharmony_ci pdman.set4fv(uniform, 1, values); 344cb93a386Sopenharmony_ci } else { 345cb93a386Sopenharmony_ci pdman.setSkMatrix(uniform, matrix); 346cb93a386Sopenharmony_ci } 347cb93a386Sopenharmony_ci} 348cb93a386Sopenharmony_ci 349cb93a386Sopenharmony_cistatic void write_passthrough_vertex_position(GrGLSLVertexBuilder* vertBuilder, 350cb93a386Sopenharmony_ci const GrShaderVar& inPos, 351cb93a386Sopenharmony_ci GrShaderVar* outPos) { 352cb93a386Sopenharmony_ci SkASSERT(inPos.getType() == kFloat3_GrSLType || inPos.getType() == kFloat2_GrSLType); 353cb93a386Sopenharmony_ci SkString outName = vertBuilder->newTmpVarName(inPos.getName().c_str()); 354cb93a386Sopenharmony_ci outPos->set(inPos.getType(), outName.c_str()); 355cb93a386Sopenharmony_ci vertBuilder->codeAppendf("float%d %s = %s;", 356cb93a386Sopenharmony_ci GrSLTypeVecLength(inPos.getType()), 357cb93a386Sopenharmony_ci outName.c_str(), 358cb93a386Sopenharmony_ci inPos.getName().c_str()); 359cb93a386Sopenharmony_ci} 360cb93a386Sopenharmony_ci 361cb93a386Sopenharmony_cistatic void write_vertex_position(GrGLSLVertexBuilder* vertBuilder, 362cb93a386Sopenharmony_ci GrGLSLUniformHandler* uniformHandler, 363cb93a386Sopenharmony_ci const GrShaderCaps& shaderCaps, 364cb93a386Sopenharmony_ci const GrShaderVar& inPos, 365cb93a386Sopenharmony_ci const SkMatrix& matrix, 366cb93a386Sopenharmony_ci const char* matrixName, 367cb93a386Sopenharmony_ci GrShaderVar* outPos, 368cb93a386Sopenharmony_ci ProgramImpl::UniformHandle* matrixUniform) { 369cb93a386Sopenharmony_ci SkASSERT(inPos.getType() == kFloat3_GrSLType || inPos.getType() == kFloat2_GrSLType); 370cb93a386Sopenharmony_ci SkString outName = vertBuilder->newTmpVarName(inPos.getName().c_str()); 371cb93a386Sopenharmony_ci 372cb93a386Sopenharmony_ci if (matrix.isIdentity() && !shaderCaps.reducedShaderMode()) { 373cb93a386Sopenharmony_ci write_passthrough_vertex_position(vertBuilder, inPos, outPos); 374cb93a386Sopenharmony_ci return; 375cb93a386Sopenharmony_ci } 376cb93a386Sopenharmony_ci SkASSERT(matrixUniform); 377cb93a386Sopenharmony_ci 378cb93a386Sopenharmony_ci bool useCompactTransform = matrix.isScaleTranslate() && !shaderCaps.reducedShaderMode(); 379cb93a386Sopenharmony_ci const char* mangledMatrixName; 380cb93a386Sopenharmony_ci *matrixUniform = uniformHandler->addUniform(nullptr, 381cb93a386Sopenharmony_ci kVertex_GrShaderFlag, 382cb93a386Sopenharmony_ci useCompactTransform ? kFloat4_GrSLType 383cb93a386Sopenharmony_ci : kFloat3x3_GrSLType, 384cb93a386Sopenharmony_ci matrixName, 385cb93a386Sopenharmony_ci &mangledMatrixName); 386cb93a386Sopenharmony_ci 387cb93a386Sopenharmony_ci if (inPos.getType() == kFloat3_GrSLType) { 388cb93a386Sopenharmony_ci // A float3 stays a float3 whether or not the matrix adds perspective 389cb93a386Sopenharmony_ci if (useCompactTransform) { 390cb93a386Sopenharmony_ci vertBuilder->codeAppendf("float3 %s = %s.xz1 * %s + %s.yw0;\n", 391cb93a386Sopenharmony_ci outName.c_str(), 392cb93a386Sopenharmony_ci mangledMatrixName, 393cb93a386Sopenharmony_ci inPos.getName().c_str(), 394cb93a386Sopenharmony_ci mangledMatrixName); 395cb93a386Sopenharmony_ci } else { 396cb93a386Sopenharmony_ci vertBuilder->codeAppendf("float3 %s = %s * %s;\n", 397cb93a386Sopenharmony_ci outName.c_str(), 398cb93a386Sopenharmony_ci mangledMatrixName, 399cb93a386Sopenharmony_ci inPos.getName().c_str()); 400cb93a386Sopenharmony_ci } 401cb93a386Sopenharmony_ci outPos->set(kFloat3_GrSLType, outName.c_str()); 402cb93a386Sopenharmony_ci return; 403cb93a386Sopenharmony_ci } 404cb93a386Sopenharmony_ci if (matrix.hasPerspective()) { 405cb93a386Sopenharmony_ci // A float2 is promoted to a float3 if we add perspective via the matrix 406cb93a386Sopenharmony_ci SkASSERT(!useCompactTransform); 407cb93a386Sopenharmony_ci vertBuilder->codeAppendf("float3 %s = (%s * %s.xy1);", 408cb93a386Sopenharmony_ci outName.c_str(), 409cb93a386Sopenharmony_ci mangledMatrixName, 410cb93a386Sopenharmony_ci inPos.getName().c_str()); 411cb93a386Sopenharmony_ci outPos->set(kFloat3_GrSLType, outName.c_str()); 412cb93a386Sopenharmony_ci return; 413cb93a386Sopenharmony_ci } 414cb93a386Sopenharmony_ci if (useCompactTransform) { 415cb93a386Sopenharmony_ci vertBuilder->codeAppendf("float2 %s = %s.xz * %s + %s.yw;\n", 416cb93a386Sopenharmony_ci outName.c_str(), 417cb93a386Sopenharmony_ci mangledMatrixName, 418cb93a386Sopenharmony_ci inPos.getName().c_str(), 419cb93a386Sopenharmony_ci mangledMatrixName); 420cb93a386Sopenharmony_ci } else if (shaderCaps.nonsquareMatrixSupport()) { 421cb93a386Sopenharmony_ci vertBuilder->codeAppendf("float2 %s = float3x2(%s) * %s.xy1;\n", 422cb93a386Sopenharmony_ci outName.c_str(), 423cb93a386Sopenharmony_ci mangledMatrixName, 424cb93a386Sopenharmony_ci inPos.getName().c_str()); 425cb93a386Sopenharmony_ci } else { 426cb93a386Sopenharmony_ci vertBuilder->codeAppendf("float2 %s = (%s * %s.xy1).xy;\n", 427cb93a386Sopenharmony_ci outName.c_str(), 428cb93a386Sopenharmony_ci mangledMatrixName, 429cb93a386Sopenharmony_ci inPos.getName().c_str()); 430cb93a386Sopenharmony_ci } 431cb93a386Sopenharmony_ci outPos->set(kFloat2_GrSLType, outName.c_str()); 432cb93a386Sopenharmony_ci} 433cb93a386Sopenharmony_ci 434cb93a386Sopenharmony_civoid ProgramImpl::WriteOutputPosition(GrGLSLVertexBuilder* vertBuilder, 435cb93a386Sopenharmony_ci GrGPArgs* gpArgs, 436cb93a386Sopenharmony_ci const char* posName) { 437cb93a386Sopenharmony_ci // writeOutputPosition assumes the incoming pos name points to a float2 variable 438cb93a386Sopenharmony_ci GrShaderVar inPos(posName, kFloat2_GrSLType); 439cb93a386Sopenharmony_ci write_passthrough_vertex_position(vertBuilder, inPos, &gpArgs->fPositionVar); 440cb93a386Sopenharmony_ci} 441cb93a386Sopenharmony_ci 442cb93a386Sopenharmony_civoid ProgramImpl::WriteOutputPosition(GrGLSLVertexBuilder* vertBuilder, 443cb93a386Sopenharmony_ci GrGLSLUniformHandler* uniformHandler, 444cb93a386Sopenharmony_ci const GrShaderCaps& shaderCaps, 445cb93a386Sopenharmony_ci GrGPArgs* gpArgs, 446cb93a386Sopenharmony_ci const char* posName, 447cb93a386Sopenharmony_ci const SkMatrix& mat, 448cb93a386Sopenharmony_ci UniformHandle* viewMatrixUniform) { 449cb93a386Sopenharmony_ci GrShaderVar inPos(posName, kFloat2_GrSLType); 450cb93a386Sopenharmony_ci write_vertex_position(vertBuilder, 451cb93a386Sopenharmony_ci uniformHandler, 452cb93a386Sopenharmony_ci shaderCaps, 453cb93a386Sopenharmony_ci inPos, 454cb93a386Sopenharmony_ci mat, 455cb93a386Sopenharmony_ci "viewMatrix", 456cb93a386Sopenharmony_ci &gpArgs->fPositionVar, 457cb93a386Sopenharmony_ci viewMatrixUniform); 458cb93a386Sopenharmony_ci} 459cb93a386Sopenharmony_ci 460cb93a386Sopenharmony_civoid ProgramImpl::WriteLocalCoord(GrGLSLVertexBuilder* vertBuilder, 461cb93a386Sopenharmony_ci GrGLSLUniformHandler* uniformHandler, 462cb93a386Sopenharmony_ci const GrShaderCaps& shaderCaps, 463cb93a386Sopenharmony_ci GrGPArgs* gpArgs, 464cb93a386Sopenharmony_ci GrShaderVar localVar, 465cb93a386Sopenharmony_ci const SkMatrix& localMatrix, 466cb93a386Sopenharmony_ci UniformHandle* localMatrixUniform) { 467cb93a386Sopenharmony_ci write_vertex_position(vertBuilder, 468cb93a386Sopenharmony_ci uniformHandler, 469cb93a386Sopenharmony_ci shaderCaps, 470cb93a386Sopenharmony_ci localVar, 471cb93a386Sopenharmony_ci localMatrix, 472cb93a386Sopenharmony_ci "localMatrix", 473cb93a386Sopenharmony_ci &gpArgs->fLocalCoordVar, 474cb93a386Sopenharmony_ci localMatrixUniform); 475cb93a386Sopenharmony_ci} 476