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 GrGLSLFragmentProcessor_DEFINED 9 #define GrGLSLFragmentProcessor_DEFINED 10 11 #include "GrFragmentProcessor.h" 12 #include "GrShaderVar.h" 13 #include "glsl/GrGLSLProgramDataManager.h" 14 #include "glsl/GrGLSLUniformHandler.h" 15 16 class GrProcessor; 17 class GrProcessorKeyBuilder; 18 class GrGLSLFPBuilder; 19 class GrGLSLFPFragmentBuilder; 20 21 class GrGLSLFragmentProcessor { 22 public: GrGLSLFragmentProcessor()23 GrGLSLFragmentProcessor() {} 24 ~GrGLSLFragmentProcessor()25 virtual ~GrGLSLFragmentProcessor() { 26 for (int i = 0; i < fChildProcessors.count(); ++i) { 27 delete fChildProcessors[i]; 28 } 29 } 30 31 using UniformHandle = GrGLSLUniformHandler::UniformHandle; 32 using SamplerHandle = GrGLSLUniformHandler::SamplerHandle; 33 using TexelBufferHandle = GrGLSLUniformHandler::TexelBufferHandle; 34 using ImageStorageHandle = GrGLSLUniformHandler::ImageStorageHandle; 35 36 private: 37 /** 38 * This class allows the shader builder to provide each GrGLSLFragmentProcesor with an array of 39 * generated variables where each generated variable corresponds to an element of an array on 40 * the GrFragmentProcessor that generated the GLSLFP. For example, this is used to provide a 41 * variable holding transformed coords for each GrCoordTransform owned by the FP. 42 */ 43 template <typename T, typename FPBASE, int (FPBASE::*COUNT)() const> 44 class BuilderInputProvider { 45 public: BuilderInputProvider(const GrFragmentProcessor * fp,const T * ts)46 BuilderInputProvider(const GrFragmentProcessor* fp, const T* ts) : fFP(fp) , fTs(ts) {} 47 48 const T& operator[] (int i) const { 49 SkASSERT(i >= 0 && i < (fFP->*COUNT)()); 50 return fTs[i]; 51 } 52 childInputs(int childIdx)53 BuilderInputProvider childInputs(int childIdx) const { 54 const GrFragmentProcessor* child = &fFP->childProcessor(childIdx); 55 GrFragmentProcessor::Iter iter(fFP); 56 int numToSkip = 0; 57 while (true) { 58 const GrFragmentProcessor* fp = iter.next(); 59 if (fp == child) { 60 return BuilderInputProvider(child, fTs + numToSkip); 61 } 62 numToSkip += (fp->*COUNT)(); 63 } 64 } 65 66 private: 67 const GrFragmentProcessor* fFP; 68 const T* fTs; 69 }; 70 71 public: 72 using TransformedCoordVars = BuilderInputProvider<GrShaderVar, GrFragmentProcessor, 73 &GrFragmentProcessor::numCoordTransforms>; 74 using TextureSamplers = BuilderInputProvider<SamplerHandle, GrResourceIOProcessor, 75 &GrResourceIOProcessor::numTextureSamplers>; 76 using TexelBuffers = BuilderInputProvider<TexelBufferHandle, GrResourceIOProcessor, 77 &GrResourceIOProcessor::numBuffers>; 78 using ImageStorages = BuilderInputProvider<ImageStorageHandle, GrResourceIOProcessor, 79 &GrResourceIOProcessor::numImageStorages>; 80 81 /** Called when the program stage should insert its code into the shaders. The code in each 82 shader will be in its own block ({}) and so locally scoped names will not collide across 83 stages. 84 85 @param fragBuilder Interface used to emit code in the shaders. 86 @param fp The processor that generated this program stage. 87 @param key The key that was computed by GenKey() from the generating 88 GrProcessor. 89 @param outputColor A predefined vec4 in the FS in which the stage should place its 90 output color (or coverage). 91 @param inputColor A vec4 that holds the input color to the stage in the FS. This may 92 be nullptr in which case the implied input is solid white (all 93 ones). TODO: Better system for communicating optimization info 94 (e.g. input color is solid white, trans black, known to be opaque, 95 etc.) that allows the processor to communicate back similar known 96 info about its output. 97 @param transformedCoords Fragment shader variables containing the coords computed using 98 each of the GrFragmentProcessor's GrCoordTransforms. 99 @param texSamplers Contains one entry for each TextureSampler of the GrProcessor. 100 These can be passed to the builder to emit texture reads in the 101 generated code. 102 @param bufferSamplers Contains one entry for each BufferAccess of the GrProcessor. These 103 can be passed to the builder to emit buffer reads in the generated 104 code. 105 @param imageStorages Contains one entry for each ImageStorageAccess of the GrProcessor. 106 These can be passed to the builder to emit image loads and stores 107 in the generated code. 108 */ 109 struct EmitArgs { EmitArgsEmitArgs110 EmitArgs(GrGLSLFPFragmentBuilder* fragBuilder, 111 GrGLSLUniformHandler* uniformHandler, 112 const GrShaderCaps* caps, 113 const GrFragmentProcessor& fp, 114 const char* outputColor, 115 const char* inputColor, 116 const TransformedCoordVars& transformedCoordVars, 117 const TextureSamplers& textureSamplers, 118 const TexelBuffers& texelBuffers, 119 const ImageStorages& imageStorages) 120 : fFragBuilder(fragBuilder) 121 , fUniformHandler(uniformHandler) 122 , fShaderCaps(caps) 123 , fFp(fp) 124 , fOutputColor(outputColor) 125 , fInputColor(inputColor) 126 , fTransformedCoords(transformedCoordVars) 127 , fTexSamplers(textureSamplers) 128 , fTexelBuffers(texelBuffers) 129 , fImageStorages(imageStorages) {} 130 GrGLSLFPFragmentBuilder* fFragBuilder; 131 GrGLSLUniformHandler* fUniformHandler; 132 const GrShaderCaps* fShaderCaps; 133 const GrFragmentProcessor& fFp; 134 const char* fOutputColor; 135 const char* fInputColor; 136 const TransformedCoordVars& fTransformedCoords; 137 const TextureSamplers& fTexSamplers; 138 const TexelBuffers& fTexelBuffers; 139 const ImageStorages& fImageStorages; 140 }; 141 142 virtual void emitCode(EmitArgs&) = 0; 143 144 void setData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor); 145 GenKey(const GrProcessor &,const GrShaderCaps &,GrProcessorKeyBuilder *)146 static void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*) {} 147 numChildProcessors()148 int numChildProcessors() const { return fChildProcessors.count(); } 149 childProcessor(int index)150 GrGLSLFragmentProcessor* childProcessor(int index) { 151 return fChildProcessors[index]; 152 } 153 emitChild(int childIndex,SkString * outputColor,EmitArgs & parentArgs)154 inline void emitChild(int childIndex, SkString* outputColor, EmitArgs& parentArgs) { 155 this->emitChild(childIndex, "vec4(1.0)", outputColor, parentArgs); 156 } 157 158 /** Will emit the code of a child proc in its own scope. Pass in the parent's EmitArgs and 159 * emitChild will automatically extract the coords and samplers of that child and pass them 160 * on to the child's emitCode(). Also, any uniforms or functions emitted by the child will 161 * have their names mangled to prevent redefinitions. The output color name is also mangled 162 * therefore in an in/out param. It will be declared in mangled form by emitChild(). It is 163 * legal to pass nullptr as inputColor, since all fragment processors are required to work 164 * without an input color. 165 */ 166 void emitChild(int childIndex, const char* inputColor, SkString* outputColor, 167 EmitArgs& parentArgs); 168 emitChild(int childIndex,EmitArgs & args)169 inline void emitChild(int childIndex, EmitArgs& args) { 170 this->emitChild(childIndex, "vec4(1.0)", args); 171 } 172 173 /** Variation that uses the parent's output color variable to hold the child's output.*/ 174 void emitChild(int childIndex, const char* inputColor, EmitArgs& parentArgs); 175 176 /** 177 * Pre-order traversal of a GLSLFP hierarchy, or of multiple trees with roots in an array of 178 * GLSLFPS. This agrees with the traversal order of GrFragmentProcessor::Iter 179 */ 180 class Iter : public SkNoncopyable { 181 public: Iter(GrGLSLFragmentProcessor * fp)182 explicit Iter(GrGLSLFragmentProcessor* fp) { fFPStack.push_back(fp); } Iter(GrGLSLFragmentProcessor * fps[],int cnt)183 explicit Iter(GrGLSLFragmentProcessor* fps[], int cnt) { 184 for (int i = cnt - 1; i >= 0; --i) { 185 fFPStack.push_back(fps[i]); 186 } 187 } 188 GrGLSLFragmentProcessor* next(); 189 190 private: 191 SkSTArray<4, GrGLSLFragmentProcessor*, true> fFPStack; 192 }; 193 194 protected: 195 /** A GrGLSLFragmentProcessor instance can be reused with any GrFragmentProcessor that produces 196 the same stage key; this function reads data from a GrFragmentProcessor and uploads any 197 uniform variables required by the shaders created in emitCode(). The GrFragmentProcessor 198 parameter is guaranteed to be of the same type that created this GrGLSLFragmentProcessor and 199 to have an identical processor key as the one that created this GrGLSLFragmentProcessor. */ onSetData(const GrGLSLProgramDataManager &,const GrFragmentProcessor &)200 virtual void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) {} 201 202 private: 203 void internalEmitChild(int, const char*, const char*, EmitArgs&); 204 205 SkTArray<GrGLSLFragmentProcessor*, true> fChildProcessors; 206 207 friend class GrFragmentProcessor; 208 }; 209 210 #endif 211