1 /* 2 * Copyright 2013 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef GrGLSLGeometryProcessor_DEFINED 9 #define GrGLSLGeometryProcessor_DEFINED 10 11 #include "src/gpu/GrFragmentProcessor.h" 12 #include "src/gpu/GrGeometryProcessor.h" 13 #include "src/gpu/glsl/GrGLSLProgramDataManager.h" 14 #include "src/gpu/glsl/GrGLSLUniformHandler.h" 15 16 class GrGeometryProcessor; 17 class GrGLSLFPFragmentBuilder; 18 class GrGLSLGeometryBuilder; 19 class GrGLSLGPBuilder; 20 class GrGLSLVaryingHandler; 21 class GrGLSLVertexBuilder; 22 class GrShaderCaps; 23 24 /** 25 * GrGeometryProcessor-derived classes that need to emit GLSL vertex shader code should be paired 26 * with a sibling class derived from GrGLSLGeometryProcessor (and return an instance of it from 27 * createGLSLInstance). 28 */ 29 class GrGLSLGeometryProcessor { 30 public: 31 using UniformHandle = GrGLSLProgramDataManager::UniformHandle; 32 using SamplerHandle = GrGLSLUniformHandler::SamplerHandle; 33 ~GrGLSLGeometryProcessor()34 virtual ~GrGLSLGeometryProcessor() {} 35 36 /** 37 * This class provides access to each GrFragmentProcessor in a GrPipeline that requires varying 38 * local coords to be produced by the primitive processor. It is also used by the primitive 39 * processor to specify the fragment shader variable that will hold the transformed coords for 40 * each of those GrFragmentProcessors. It is required that the primitive processor iterate over 41 * each fragment processor and insert a shader var result for each. The GrGLSLFragmentProcessors 42 * will reference these variables in their fragment code. 43 */ 44 class FPCoordTransformHandler : public SkNoncopyable { 45 public: 46 FPCoordTransformHandler(const GrPipeline&, SkTArray<GrShaderVar>*); ~FPCoordTransformHandler()47 ~FPCoordTransformHandler() { SkASSERT(!fIter); } 48 49 operator bool() const { return (bool)fIter; } 50 51 // Gets the current GrFragmentProcessor 52 const GrFragmentProcessor& get() const; 53 54 FPCoordTransformHandler& operator++(); 55 specifyCoordsForCurrCoordTransform(GrShaderVar varyingVar)56 void specifyCoordsForCurrCoordTransform(GrShaderVar varyingVar) { 57 SkASSERT(!fAddedCoord); 58 fTransformedCoordVars->push_back(varyingVar); 59 SkDEBUGCODE(fAddedCoord = true;) 60 } 61 62 private: 63 GrFragmentProcessor::CIter fIter; 64 SkDEBUGCODE(bool fAddedCoord = false;) 65 SkTArray<GrShaderVar>* fTransformedCoordVars; 66 }; 67 68 struct EmitArgs { EmitArgsEmitArgs69 EmitArgs(GrGLSLVertexBuilder* vertBuilder, 70 GrGLSLGeometryBuilder* geomBuilder, 71 GrGLSLFPFragmentBuilder* fragBuilder, 72 GrGLSLVaryingHandler* varyingHandler, 73 GrGLSLUniformHandler* uniformHandler, 74 const GrShaderCaps* caps, 75 const GrGeometryProcessor& geomProc, 76 const char* outputColor, 77 const char* outputCoverage, 78 const SamplerHandle* texSamplers, 79 FPCoordTransformHandler* transformHandler) 80 : fVertBuilder(vertBuilder) 81 , fGeomBuilder(geomBuilder) 82 , fFragBuilder(fragBuilder) 83 , fVaryingHandler(varyingHandler) 84 , fUniformHandler(uniformHandler) 85 , fShaderCaps(caps) 86 , fGeomProc(geomProc) 87 , fOutputColor(outputColor) 88 , fOutputCoverage(outputCoverage) 89 , fTexSamplers(texSamplers) 90 , fFPCoordTransformHandler(transformHandler) {} 91 GrGLSLVertexBuilder* fVertBuilder; 92 GrGLSLGeometryBuilder* fGeomBuilder; 93 GrGLSLFPFragmentBuilder* fFragBuilder; 94 GrGLSLVaryingHandler* fVaryingHandler; 95 GrGLSLUniformHandler* fUniformHandler; 96 const GrShaderCaps* fShaderCaps; 97 const GrGeometryProcessor& fGeomProc; 98 const char* fOutputColor; 99 const char* fOutputCoverage; 100 const SamplerHandle* fTexSamplers; 101 FPCoordTransformHandler* fFPCoordTransformHandler; 102 }; 103 104 /* Any general emit code goes in the base class emitCode. Subclasses override onEmitCode */ 105 void emitCode(EmitArgs&); 106 107 /** 108 * Called after all effect emitCode() functions, to give the processor a chance to write out 109 * additional transformation code now that all uniforms have been emitted. 110 * It generates the final code for assigning transformed coordinates to the varyings recorded 111 * in the call to collectTransforms(). This must happen after FP code emission so that it has 112 * access to any uniforms the FPs registered for uniform sample matrix invocations. 113 */ 114 void emitTransformCode(GrGLSLVertexBuilder* vb, 115 GrGLSLUniformHandler* uniformHandler); 116 117 /** 118 * A GrGLSLGeometryProcessor instance can be reused with any GrGLSLGeometryProcessor that 119 * produces the same stage key; this function reads data from a GrGLSLGeometryProcessor and 120 * uploads any uniform variables required by the shaders created in emitCode(). The 121 * GrGeometryProcessor parameter is guaranteed to be of the same type and to have an 122 * identical processor key as the GrGeometryProcessor that created this 123 * GrGLSLGeometryProcessor. 124 * The subclass should use the transform range to perform any setup required for the coord 125 * transforms of the FPs that are part of the same program, such as updating matrix uniforms. 126 * The range will iterate over the transforms in the same order as the TransformHandler passed 127 * to emitCode. 128 */ 129 virtual void setData(const GrGLSLProgramDataManager&, 130 const GrShaderCaps&, 131 const GrGeometryProcessor&) = 0; 132 133 // We use these methods as a temporary back door to inject OpenGL tessellation code. Once 134 // tessellation is supported by SkSL we can remove these. getTessControlShaderGLSL(const GrGeometryProcessor &,const char * versionAndExtensionDecls,const GrGLSLUniformHandler &,const GrShaderCaps &)135 virtual SkString getTessControlShaderGLSL(const GrGeometryProcessor&, 136 const char* versionAndExtensionDecls, 137 const GrGLSLUniformHandler&, 138 const GrShaderCaps&) const { 139 SK_ABORT("Not implemented."); 140 } getTessEvaluationShaderGLSL(const GrGeometryProcessor &,const char * versionAndExtensionDecls,const GrGLSLUniformHandler &,const GrShaderCaps &)141 virtual SkString getTessEvaluationShaderGLSL(const GrGeometryProcessor&, 142 const char* versionAndExtensionDecls, 143 const GrGLSLUniformHandler&, 144 const GrShaderCaps&) const { 145 SK_ABORT("Not implemented."); 146 } 147 148 protected: 149 void setupUniformColor(GrGLSLFPFragmentBuilder* fragBuilder, 150 GrGLSLUniformHandler* uniformHandler, 151 const char* outputName, 152 UniformHandle* colorUniform); 153 154 // A helper for setting the matrix on a uniform handle initialized through 155 // writeOutputPosition or writeLocalCoord. Automatically handles elided uniforms, 156 // scale+translate matrices, and state tracking (if provided state pointer is non-null). 157 static void SetTransform(const GrGLSLProgramDataManager&, 158 const GrShaderCaps&, 159 const UniformHandle& uniform, 160 const SkMatrix& matrix, 161 SkMatrix* state = nullptr); 162 163 struct GrGPArgs { 164 // Used to specify the output variable used by the GP to store its device position. It can 165 // either be a float2 or a float3 (in order to handle perspective). The subclass sets this 166 // in its onEmitCode(). 167 GrShaderVar fPositionVar; 168 // Used to specify the variable storing the draw's local coordinates. It can be either a 169 // float2, float3, or void. It can only be void when no FP needs local coordinates. This 170 // variable can be an attribute or local variable, but should not itself be a varying. 171 // GrGLSLGeometryProcessor automatically determines if this must be passed to a FS. 172 GrShaderVar fLocalCoordVar; 173 }; 174 175 // Helpers for adding code to write the transformed vertex position. The first simple version 176 // just writes a variable named by 'posName' into the position output variable with the 177 // assumption that the position is 2D. The second version transforms the input position by a 178 // view matrix and the output variable is 2D or 3D depending on whether the view matrix is 179 // perspective. Both versions declare the output position variable and will set 180 // GrGPArgs::fPositionVar. 181 static void WriteOutputPosition(GrGLSLVertexBuilder*, GrGPArgs*, const char* posName); 182 static void WriteOutputPosition(GrGLSLVertexBuilder*, 183 GrGLSLUniformHandler*, 184 const GrShaderCaps&, 185 GrGPArgs*, 186 const char* posName, 187 const SkMatrix& viewMatrix, 188 UniformHandle* viewMatrixUniform); 189 190 // Helper to transform an existing variable by a given local matrix (e.g. the inverse view 191 // matrix). It will declare the transformed local coord variable and will set 192 // GrGPArgs::fLocalCoordVar. 193 static void WriteLocalCoord(GrGLSLVertexBuilder*, 194 GrGLSLUniformHandler*, 195 const GrShaderCaps&, 196 GrGPArgs*, 197 GrShaderVar localVar, 198 const SkMatrix& localMatrix, 199 UniformHandle* localMatrixUniform); 200 201 // GPs that use writeOutputPosition and/or writeLocalCoord must incorporate the matrix type 202 // into their key, and should use this function or one of the other related helpers. ComputeMatrixKey(const GrShaderCaps & caps,const SkMatrix & mat)203 static uint32_t ComputeMatrixKey(const GrShaderCaps& caps, const SkMatrix& mat) { 204 if (!caps.reducedShaderMode()) { 205 if (mat.isIdentity()) { 206 return 0b00; 207 } 208 if (mat.isScaleTranslate()) { 209 return 0b01; 210 } 211 } 212 if (!mat.hasPerspective()) { 213 return 0b10; 214 } 215 return 0b11; 216 } ComputeMatrixKeys(const GrShaderCaps & shaderCaps,const SkMatrix & viewMatrix,const SkMatrix & localMatrix)217 static uint32_t ComputeMatrixKeys(const GrShaderCaps& shaderCaps, 218 const SkMatrix& viewMatrix, 219 const SkMatrix& localMatrix) { 220 return (ComputeMatrixKey(shaderCaps, viewMatrix) << kMatrixKeyBits) | 221 ComputeMatrixKey(shaderCaps, localMatrix); 222 } AddMatrixKeys(const GrShaderCaps & shaderCaps,uint32_t flags,const SkMatrix & viewMatrix,const SkMatrix & localMatrix)223 static uint32_t AddMatrixKeys(const GrShaderCaps& shaderCaps, 224 uint32_t flags, 225 const SkMatrix& viewMatrix, 226 const SkMatrix& localMatrix) { 227 // Shifting to make room for the matrix keys shouldn't lose bits 228 SkASSERT(((flags << (2 * kMatrixKeyBits)) >> (2 * kMatrixKeyBits)) == flags); 229 return (flags << (2 * kMatrixKeyBits)) | 230 ComputeMatrixKeys(shaderCaps, viewMatrix, localMatrix); 231 } 232 static constexpr int kMatrixKeyBits = 2; 233 234 private: 235 virtual void onEmitCode(EmitArgs&, GrGPArgs*) = 0; 236 237 // Iterates over the FPs in 'handler' to register additional varyings and uniforms to support 238 // VS-promoted local coord evaluation for the FPs. Subclasses must call this with 239 // 'localCoordsVar' set to an SkSL variable expression of type 'float2' or 'float3' representing 240 // the original local coordinates of the draw. 241 // 242 // This must happen before FP code emission so that the FPs can find the appropriate varying 243 // handles they use in place of explicit coord sampling; it is automatically called after 244 // onEmitCode() returns using the value stored in GpArgs::fLocalCoordVar. 245 void collectTransforms(GrGLSLVertexBuilder* vb, 246 GrGLSLVaryingHandler* varyingHandler, 247 GrGLSLUniformHandler* uniformHandler, 248 const GrShaderVar& localCoordsVar, 249 FPCoordTransformHandler* handler); 250 251 struct TransformInfo { 252 // The vertex-shader output variable to assign the transformed coordinates to 253 GrShaderVar fOutputCoords; 254 // The coordinate to be transformed 255 GrShaderVar fLocalCoords; 256 // The leaf FP of a transform hierarchy to be evaluated in the vertex shader; 257 // this FP will be const-uniform sampled, and all of its parents will have a sample matrix 258 // type of none or const-uniform. 259 const GrFragmentProcessor* fFP; 260 }; 261 SkTArray<TransformInfo> fTransformInfos; 262 }; 263 264 #endif 265