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 16class GrProcessor; 17class GrProcessorKeyBuilder; 18class GrGLSLFPBuilder; 19class GrGLSLFPFragmentBuilder; 20 21class GrGLSLFragmentProcessor { 22public: 23 GrGLSLFragmentProcessor() {} 24 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 35private: 36 /** 37 * This class allows the shader builder to provide each GrGLSLFragmentProcesor with an array of 38 * generated variables where each generated variable corresponds to an element of an array on 39 * the GrFragmentProcessor that generated the GLSLFP. For example, this is used to provide a 40 * variable holding transformed coords for each GrCoordTransform owned by the FP. 41 */ 42 template <typename T, typename FPBASE, int (FPBASE::*COUNT)() const> 43 class BuilderInputProvider { 44 public: 45 BuilderInputProvider(const GrFragmentProcessor* fp, const T* ts) : fFP(fp) , fTs(ts) {} 46 47 const T& operator[] (int i) const { 48 SkASSERT(i >= 0 && i < (fFP->*COUNT)()); 49 return fTs[i]; 50 } 51 52 BuilderInputProvider childInputs(int childIdx) const { 53 const GrFragmentProcessor* child = &fFP->childProcessor(childIdx); 54 GrFragmentProcessor::Iter iter(fFP); 55 int numToSkip = 0; 56 while (true) { 57 const GrFragmentProcessor* fp = iter.next(); 58 if (fp == child) { 59 return BuilderInputProvider(child, fTs + numToSkip); 60 } 61 numToSkip += (fp->*COUNT)(); 62 } 63 } 64 65 private: 66 const GrFragmentProcessor* fFP; 67 const T* fTs; 68 }; 69 70public: 71 using TransformedCoordVars = BuilderInputProvider<GrShaderVar, GrFragmentProcessor, 72 &GrFragmentProcessor::numCoordTransforms>; 73 using TextureSamplers = BuilderInputProvider<SamplerHandle, GrResourceIOProcessor, 74 &GrResourceIOProcessor::numTextureSamplers>; 75 using TexelBuffers = BuilderInputProvider<TexelBufferHandle, GrResourceIOProcessor, 76 &GrResourceIOProcessor::numBuffers>; 77 78 /** Called when the program stage should insert its code into the shaders. The code in each 79 shader will be in its own block ({}) and so locally scoped names will not collide across 80 stages. 81 82 @param fragBuilder Interface used to emit code in the shaders. 83 @param fp The processor that generated this program stage. 84 @param key The key that was computed by GenKey() from the generating 85 GrProcessor. 86 @param outputColor A predefined half4 in the FS in which the stage should place its 87 output color (or coverage). 88 @param inputColor A half4 that holds the input color to the stage in the FS. This may 89 be nullptr in which case the implied input is solid white (all 90 ones). 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 @param bufferSamplers Contains one entry for each BufferAccess of the GrProcessor. These 100 can be passed to the builder to emit buffer reads in the generated 101 code. 102 */ 103 struct EmitArgs { 104 EmitArgs(GrGLSLFPFragmentBuilder* fragBuilder, 105 GrGLSLUniformHandler* uniformHandler, 106 const GrShaderCaps* caps, 107 const GrFragmentProcessor& fp, 108 const char* outputColor, 109 const char* inputColor, 110 const TransformedCoordVars& transformedCoordVars, 111 const TextureSamplers& textureSamplers, 112 const TexelBuffers& texelBuffers) 113 : fFragBuilder(fragBuilder) 114 , fUniformHandler(uniformHandler) 115 , fShaderCaps(caps) 116 , fFp(fp) 117 , fOutputColor(outputColor) 118 , fInputColor(inputColor) 119 , fTransformedCoords(transformedCoordVars) 120 , fTexSamplers(textureSamplers) 121 , fTexelBuffers(texelBuffers) {} 122 GrGLSLFPFragmentBuilder* fFragBuilder; 123 GrGLSLUniformHandler* fUniformHandler; 124 const GrShaderCaps* fShaderCaps; 125 const GrFragmentProcessor& fFp; 126 const char* fOutputColor; 127 const char* fInputColor; 128 const TransformedCoordVars& fTransformedCoords; 129 const TextureSamplers& fTexSamplers; 130 const TexelBuffers& fTexelBuffers; 131 }; 132 133 virtual void emitCode(EmitArgs&) = 0; 134 135 void setData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor); 136 137 int numChildProcessors() const { return fChildProcessors.count(); } 138 139 GrGLSLFragmentProcessor* childProcessor(int index) { 140 return fChildProcessors[index]; 141 } 142 143 inline void emitChild(int childIndex, SkString* outputColor, EmitArgs& parentArgs) { 144 this->emitChild(childIndex, "half4(1.0)", outputColor, parentArgs); 145 } 146 147 /** Will emit the code of a child proc in its own scope. Pass in the parent's EmitArgs and 148 * emitChild will automatically extract the coords and samplers of that child and pass them 149 * on to the child's emitCode(). Also, any uniforms or functions emitted by the child will 150 * have their names mangled to prevent redefinitions. The output color name is also mangled 151 * therefore in an in/out param. It will be declared in mangled form by emitChild(). It is 152 * legal to pass nullptr as inputColor, since all fragment processors are required to work 153 * without an input color. 154 */ 155 void emitChild(int childIndex, const char* inputColor, SkString* outputColor, 156 EmitArgs& parentArgs); 157 158 inline void emitChild(int childIndex, EmitArgs& args) { 159 this->emitChild(childIndex, "half4(1.0)", args); 160 } 161 162 /** Variation that uses the parent's output color variable to hold the child's output.*/ 163 void emitChild(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: 171 explicit Iter(GrGLSLFragmentProcessor* fp) { fFPStack.push_back(fp); } 172 explicit Iter(GrGLSLFragmentProcessor* fps[], int cnt) { 173 for (int i = cnt - 1; i >= 0; --i) { 174 fFPStack.push_back(fps[i]); 175 } 176 } 177 GrGLSLFragmentProcessor* next(); 178 179 private: 180 SkSTArray<4, GrGLSLFragmentProcessor*, true> fFPStack; 181 }; 182 183protected: 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. */ 189 virtual void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) {} 190 191private: 192 void internalEmitChild(int, const char*, const char*, EmitArgs&); 193 194 SkTArray<GrGLSLFragmentProcessor*, true> fChildProcessors; 195 196 friend class GrFragmentProcessor; 197}; 198 199#endif 200