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 "src/gpu/GrFragmentProcessor.h" 12 #include "src/gpu/GrShaderVar.h" 13 #include "src/gpu/glsl/GrGLSLProgramDataManager.h" 14 #include "src/gpu/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 34 private: 35 /** 36 * This class allows the shader builder to provide each GrGLSLFragmentProcesor with an array of 37 * generated variables where each generated variable corresponds to an element of an array on 38 * the GrFragmentProcessor that generated the GLSLFP. For example, this is used to provide a 39 * variable holding transformed coords for each GrCoordTransform owned by the FP. 40 */ 41 template <typename T, int (GrFragmentProcessor::*COUNT)() const> 42 class BuilderInputProvider { 43 public: BuilderInputProvider(const GrFragmentProcessor * fp,const T * ts)44 BuilderInputProvider(const GrFragmentProcessor* fp, const T* ts) : fFP(fp) , fTs(ts) {} 45 46 const T& operator[] (int i) const { 47 SkASSERT(i >= 0 && i < (fFP->*COUNT)()); 48 return fTs[i]; 49 } 50 count()51 int count() const { return (fFP->*COUNT)(); } 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 = 73 BuilderInputProvider<GrShaderVar, &GrFragmentProcessor::numCoordTransforms>; 74 using TextureSamplers = 75 BuilderInputProvider<SamplerHandle, &GrFragmentProcessor::numTextureSamplers>; 76 77 /** Called when the program stage should insert its code into the shaders. The code in each 78 shader will be in its own block ({}) and so locally scoped names will not collide across 79 stages. 80 81 @param fragBuilder Interface used to emit code in the shaders. 82 @param fp The processor that generated this program stage. 83 @param key The key that was computed by GenKey() from the generating 84 GrProcessor. 85 @param outputColor A predefined half4 in the FS in which the stage should place its 86 output color (or coverage). 87 @param inputColor A half4 that holds the input color to the stage in the FS. This may 88 be nullptr in which case the fInputColor is set to "half4(1.0)" 89 (solid white) so this is guaranteed non-null. 90 TODO: Better system for communicating optimization info 91 (e.g. input color is solid white, trans black, known to be opaque, 92 etc.) that allows the processor to communicate back similar known 93 info about its output. 94 @param transformedCoords Fragment shader variables containing the coords computed using 95 each of the GrFragmentProcessor's GrCoordTransforms. 96 @param texSamplers Contains one entry for each TextureSampler of the GrProcessor. 97 These can be passed to the builder to emit texture reads in the 98 generated code. 99 */ 100 struct EmitArgs { EmitArgsEmitArgs101 EmitArgs(GrGLSLFPFragmentBuilder* fragBuilder, 102 GrGLSLUniformHandler* uniformHandler, 103 const GrShaderCaps* caps, 104 const GrFragmentProcessor& fp, 105 const char* outputColor, 106 const char* inputColor, 107 const TransformedCoordVars& transformedCoordVars, 108 const TextureSamplers& textureSamplers) 109 : fFragBuilder(fragBuilder) 110 , fUniformHandler(uniformHandler) 111 , fShaderCaps(caps) 112 , fFp(fp) 113 , fOutputColor(outputColor) 114 , fInputColor(inputColor ? inputColor : "half4(1.0)") 115 , fTransformedCoords(transformedCoordVars) 116 , fTexSamplers(textureSamplers) {} 117 GrGLSLFPFragmentBuilder* fFragBuilder; 118 GrGLSLUniformHandler* fUniformHandler; 119 const GrShaderCaps* fShaderCaps; 120 const GrFragmentProcessor& fFp; 121 const char* fOutputColor; 122 const char* fInputColor; 123 const TransformedCoordVars& fTransformedCoords; 124 const TextureSamplers& fTexSamplers; 125 }; 126 127 virtual void emitCode(EmitArgs&) = 0; 128 129 // This does not recurse to any attached child processors. Recursing the entire processor tree 130 // is the responsibility of the caller. 131 void setData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor); 132 numChildProcessors()133 int numChildProcessors() const { return fChildProcessors.count(); } 134 childProcessor(int index)135 GrGLSLFragmentProcessor* childProcessor(int index) { 136 return fChildProcessors[index]; 137 } 138 139 // Invoke the child with the default input color (solid white) invokeChild(int childIndex,SkString * outputColor,EmitArgs & parentArgs)140 inline void invokeChild(int childIndex, SkString* outputColor, EmitArgs& parentArgs) { 141 this->invokeChild(childIndex, nullptr, outputColor, parentArgs); 142 } 143 144 /** Invokes a child proc in its own scope. Pass in the parent's EmitArgs and invokeChild will 145 * automatically extract the coords and samplers of that child and pass them on to the child's 146 * emitCode(). Also, any uniforms or functions emitted by the child will have their names 147 * mangled to prevent redefinitions. The output color name is also mangled therefore in an 148 * in/out param. It will be declared in mangled form by invokeChild(). It is legal to pass 149 * nullptr as inputColor, since all fragment processors are required to work without an input 150 * color. 151 */ 152 void invokeChild(int childIndex, const char* inputColor, SkString* outputColor, 153 EmitArgs& parentArgs); 154 155 // Use the parent's output color to hold child's output, and use the 156 // default input color of solid white invokeChild(int childIndex,EmitArgs & args)157 inline void invokeChild(int childIndex, EmitArgs& args) { 158 // null pointer cast required to disambiguate the function call 159 this->invokeChild(childIndex, (const char*) nullptr, args); 160 } 161 162 /** Variation that uses the parent's output color variable to hold the child's output.*/ 163 void invokeChild(int childIndex, const char* inputColor, EmitArgs& parentArgs); 164 165 /** 166 * Pre-order traversal of a GLSLFP hierarchy, or of multiple trees with roots in an array of 167 * GLSLFPS. This agrees with the traversal order of GrFragmentProcessor::Iter 168 */ 169 class Iter : public SkNoncopyable { 170 public: Iter(GrGLSLFragmentProcessor * fp)171 explicit Iter(GrGLSLFragmentProcessor* fp) { fFPStack.push_back(fp); } Iter(std::unique_ptr<GrGLSLFragmentProcessor> fps[],int cnt)172 explicit Iter(std::unique_ptr<GrGLSLFragmentProcessor> fps[], int cnt) { 173 for (int i = cnt - 1; i >= 0; --i) { 174 fFPStack.push_back(fps[i].get()); 175 } 176 } 177 GrGLSLFragmentProcessor* next(); 178 179 private: 180 SkSTArray<4, GrGLSLFragmentProcessor*, true> fFPStack; 181 }; 182 183 protected: 184 /** A GrGLSLFragmentProcessor instance can be reused with any GrFragmentProcessor that produces 185 the same stage key; this function reads data from a GrFragmentProcessor and uploads any 186 uniform variables required by the shaders created in emitCode(). The GrFragmentProcessor 187 parameter is guaranteed to be of the same type that created this GrGLSLFragmentProcessor and 188 to have an identical processor key as the one that created this GrGLSLFragmentProcessor. */ onSetData(const GrGLSLProgramDataManager &,const GrFragmentProcessor &)189 virtual void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) {} 190 191 private: 192 void internalInvokeChild(int, const char*, const char*, EmitArgs&); 193 194 // one per child; either not present or empty string if not yet emitted 195 SkTArray<SkString> fFunctionNames; 196 197 SkTArray<GrGLSLFragmentProcessor*, true> fChildProcessors; 198 199 friend class GrFragmentProcessor; 200 }; 201 202 #endif 203