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 "include/private/SkSLString.h" 12 #include "src/gpu/GrFragmentProcessor.h" 13 #include "src/gpu/GrShaderVar.h" 14 #include "src/gpu/glsl/GrGLSLProgramDataManager.h" 15 #include "src/gpu/glsl/GrGLSLUniformHandler.h" 16 17 class GrProcessor; 18 class GrProcessorKeyBuilder; 19 class GrGLSLFPBuilder; 20 class GrGLSLFPFragmentBuilder; 21 22 class GrGLSLFragmentProcessor { 23 public: 24 GrGLSLFragmentProcessor() = default; 25 26 virtual ~GrGLSLFragmentProcessor() = default; 27 28 using UniformHandle = GrGLSLUniformHandler::UniformHandle; 29 using SamplerHandle = GrGLSLUniformHandler::SamplerHandle; 30 31 private: 32 /** 33 * This class allows the shader builder to provide each GrGLSLFragmentProcessor with an array of 34 * generated variables where each generated variable corresponds to an element of an array on 35 * the GrFragmentProcessor that generated the GLSLFP. For example, this is used to provide a 36 * variable holding transformed coords for each GrCoordTransform owned by the FP. 37 */ 38 template <typename T, int (GrFragmentProcessor::*COUNT)() const> 39 class BuilderInputProvider { 40 public: BuilderInputProvider(const GrFragmentProcessor * fp,const T * ts)41 BuilderInputProvider(const GrFragmentProcessor* fp, const T* ts) : fFP(fp) , fTs(ts) {} 42 43 const T& operator[] (int i) const { 44 SkASSERT(i >= 0 && i < (fFP->*COUNT)()); 45 return fTs[i]; 46 } 47 count()48 int count() const { return (fFP->*COUNT)(); } 49 childInputs(int childIdx)50 BuilderInputProvider childInputs(int childIdx) const { 51 const GrFragmentProcessor* child = fFP->childProcessor(childIdx); 52 SkASSERT(child); 53 int numToSkip = 0; 54 for (const auto& fp : GrFragmentProcessor::FPRange(*fFP)) { 55 if (&fp == child) { 56 return BuilderInputProvider(child, fTs + numToSkip); 57 } 58 numToSkip += (fp.*COUNT)(); 59 } 60 SK_ABORT("Didn't find the child."); 61 return {nullptr, nullptr}; 62 } 63 64 private: 65 const GrFragmentProcessor* fFP; 66 const T* fTs; 67 }; 68 69 public: 70 using TransformedCoordVars = 71 BuilderInputProvider<GrShaderVar, &GrFragmentProcessor::numVaryingCoordsUsed>; 72 73 /** Called when the program stage should insert its code into the shaders. The code in each 74 shader will be in its own block ({}) and so locally scoped names will not collide across 75 stages. 76 77 @param fragBuilder Interface used to emit code in the shaders. 78 @param fp The processor that generated this program stage. 79 @param key The key that was computed by GenKey() from the generating 80 GrProcessor. 81 @param outputColor A predefined half4 in the FS in which the stage should place its 82 output color (or coverage). 83 @param inputColor A half4 that holds the input color to the stage in the FS. This may 84 be nullptr in which case the fInputColor is set to "half4(1.0)" 85 (solid white) so this is guaranteed non-null. 86 TODO: Better system for communicating optimization info 87 (e.g. input color is solid white, trans black, known to be opaque, 88 etc.) that allows the processor to communicate back similar known 89 info about its output. 90 @param localCoord The name of a local coord reference to a float2 variable. 91 @param transformedCoords Fragment shader variables containing the coords computed using 92 each of the GrFragmentProcessor's GrCoordTransforms. 93 */ 94 struct EmitArgs { EmitArgsEmitArgs95 EmitArgs(GrGLSLFPFragmentBuilder* fragBuilder, 96 GrGLSLUniformHandler* uniformHandler, 97 const GrShaderCaps* caps, 98 const GrFragmentProcessor& fp, 99 const char* inputColor, 100 const char* sampleCoord, 101 const TransformedCoordVars& transformedCoordVars) 102 : fFragBuilder(fragBuilder) 103 , fUniformHandler(uniformHandler) 104 , fShaderCaps(caps) 105 , fFp(fp) 106 , fInputColor(inputColor ? inputColor : "half4(1.0)") 107 , fSampleCoord(sampleCoord) 108 , fTransformedCoords(transformedCoordVars) {} 109 GrGLSLFPFragmentBuilder* fFragBuilder; 110 GrGLSLUniformHandler* fUniformHandler; 111 const GrShaderCaps* fShaderCaps; 112 const GrFragmentProcessor& fFp; 113 const char* fInputColor; 114 const char* fSampleCoord; 115 const TransformedCoordVars& fTransformedCoords; 116 }; 117 118 virtual void emitCode(EmitArgs&) = 0; 119 120 // This does not recurse to any attached child processors. Recursing the entire processor tree 121 // is the responsibility of the caller. 122 void setData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor); 123 numChildProcessors()124 int numChildProcessors() const { return fChildProcessors.count(); } 125 childProcessor(int index)126 GrGLSLFragmentProcessor* childProcessor(int index) const { 127 return fChildProcessors[index].get(); 128 } 129 130 void emitChildFunction(int childIndex, EmitArgs& parentArgs); 131 132 // Invoke the child with the default input color (solid white) 133 inline SkString invokeChild(int childIndex, EmitArgs& parentArgs, 134 SkSL::String skslCoords = "") { 135 return this->invokeChild(childIndex, nullptr, parentArgs, skslCoords); 136 } 137 invokeChildWithMatrix(int childIndex,EmitArgs & parentArgs)138 inline SkString invokeChildWithMatrix(int childIndex, EmitArgs& parentArgs) { 139 return this->invokeChildWithMatrix(childIndex, nullptr, parentArgs); 140 } 141 142 /** Invokes a child proc in its own scope. Pass in the parent's EmitArgs and invokeChild will 143 * automatically extract the coords and samplers of that child and pass them on to the child's 144 * emitCode(). Also, any uniforms or functions emitted by the child will have their names 145 * mangled to prevent redefinitions. The returned string contains the output color (as a call 146 * to the child's helper function). It is legal to pass nullptr as inputColor, since all 147 * fragment processors are required to work without an input color. 148 * 149 * When skslCoords is empty, invokeChild corresponds to a call to "sample(child, color)" 150 * in SkSL. When skslCoords is not empty, invokeChild corresponds to a call to 151 * "sample(child, color, float2)", where skslCoords is an SkSL expression that evaluates to a 152 * float2 and is passed in as the 3rd argument. 153 */ 154 SkString invokeChild(int childIndex, const char* inputColor, EmitArgs& parentArgs, 155 SkSL::String skslCoords = ""); 156 157 /** 158 * As invokeChild, but transforms the coordinates according to the matrix expression attached 159 * to the child's SampleUsage object. This is only valid if the child is sampled with a 160 * const-uniform matrix. 161 */ 162 SkString invokeChildWithMatrix(int childIndex, const char* inputColor, EmitArgs& parentArgs); 163 164 /** 165 * Pre-order traversal of a GLSLFP hierarchy, or of multiple trees with roots in an array of 166 * GLSLFPS. If initialized with an array color followed by coverage processors installed in a 167 * program thenthe iteration order will agree with a GrFragmentProcessor::Iter initialized with 168 * a GrPipeline that produces the same program key. 169 */ 170 class Iter { 171 public: 172 Iter(std::unique_ptr<GrGLSLFragmentProcessor> fps[], int cnt); Iter(GrGLSLFragmentProcessor & fp)173 Iter(GrGLSLFragmentProcessor& fp) { fFPStack.push_back(&fp); } 174 175 GrGLSLFragmentProcessor& operator*() const; 176 GrGLSLFragmentProcessor* operator->() const; 177 Iter& operator++(); 178 operator bool() const { return !fFPStack.empty(); } 179 180 // Because each iterator carries a stack we want to avoid copies. 181 Iter(const Iter&) = delete; 182 Iter& operator=(const Iter&) = delete; 183 184 private: 185 SkSTArray<4, GrGLSLFragmentProcessor*, true> fFPStack; 186 }; 187 188 class ParallelIterEnd {}; 189 190 /** 191 * Walks parallel trees of GrFragmentProcessor and associated GrGLSLFragmentProcessors. The 192 * GrGLSLFragmentProcessor used to initialize the iterator must have been created by calling 193 * GrFragmentProcessor::createGLSLInstance() on the passed GrFragmentProcessor. 194 */ 195 class ParallelIter { 196 public: 197 ParallelIter(const GrFragmentProcessor& fp, GrGLSLFragmentProcessor& glslFP); 198 199 ParallelIter& operator++(); 200 201 std::tuple<const GrFragmentProcessor&, GrGLSLFragmentProcessor&> operator*() const; 202 203 bool operator==(const ParallelIterEnd& end) const; 204 205 bool operator!=(const ParallelIterEnd& end) const { return !(*this == end); } 206 207 private: 208 GrFragmentProcessor::CIter fpIter; 209 GrGLSLFragmentProcessor::Iter glslIter; 210 }; 211 212 class ParallelRange { 213 public: 214 ParallelRange(const GrFragmentProcessor& fp, GrGLSLFragmentProcessor& glslFP); 215 begin()216 ParallelIter begin() { return {fInitialFP, fInitialGLSLFP}; } 217 end()218 ParallelIterEnd end() { return {}; } 219 220 private: 221 const GrFragmentProcessor& fInitialFP; 222 GrGLSLFragmentProcessor& fInitialGLSLFP; 223 }; 224 225 protected: 226 /** A GrGLSLFragmentProcessor instance can be reused with any GrFragmentProcessor that produces 227 the same stage key; this function reads data from a GrFragmentProcessor and uploads any 228 uniform variables required by the shaders created in emitCode(). The GrFragmentProcessor 229 parameter is guaranteed to be of the same type that created this GrGLSLFragmentProcessor and 230 to have an identical processor key as the one that created this GrGLSLFragmentProcessor. */ onSetData(const GrGLSLProgramDataManager &,const GrFragmentProcessor &)231 virtual void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) {} 232 233 private: 234 // one per child; either not present or empty string if not yet emitted 235 SkTArray<SkString> fFunctionNames; 236 237 SkTArray<std::unique_ptr<GrGLSLFragmentProcessor>, true> fChildProcessors; 238 239 friend class GrFragmentProcessor; 240 }; 241 242 #endif 243