| 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/GrGLSLPrimitiveProcessor.h" |
| 14 | #include "src/gpu/glsl/GrGLSLProgramDataManager.h" |
| 15 | #include "src/gpu/glsl/GrGLSLUniformHandler.h" |
| 16 | #include "src/sksl/SkSLString.h" |
| 17 | |
| 18 | class GrProcessor; |
| 19 | class GrProcessorKeyBuilder; |
| 20 | class GrGLSLFPBuilder; |
| 21 | class GrGLSLFPFragmentBuilder; |
| 22 | |
| 23 | class GrGLSLFragmentProcessor { |
| 24 | public: |
| 25 | GrGLSLFragmentProcessor() {} |
| 26 | |
| 27 | virtual ~GrGLSLFragmentProcessor() { |
| 28 | for (int i = 0; i < fChildProcessors.count(); ++i) { |
| 29 | delete fChildProcessors[i]; |
| 30 | } |
| 31 | } |
| 32 | |
| 33 | using UniformHandle = GrGLSLUniformHandler::UniformHandle; |
| 34 | using SamplerHandle = GrGLSLUniformHandler::SamplerHandle; |
| 35 | |
| 36 | private: |
| 37 | /** |
| 38 | * This class allows the shader builder to provide each GrGLSLFragmentProcessor 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, int (GrFragmentProcessor::*COUNT)() const> |
| 44 | class BuilderInputProvider { |
| 45 | public: |
| 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 | |
| 53 | int count() const { return (fFP->*COUNT)(); } |
| 54 | |
| 55 | BuilderInputProvider childInputs(int childIdx) const { |
| 56 | const GrFragmentProcessor* child = &fFP->childProcessor(childIdx); |
| 57 | int numToSkip = 0; |
| 58 | for (const auto& fp : GrFragmentProcessor::FPCRange(*fFP)) { |
| 59 | if (&fp == child) { |
| 60 | return BuilderInputProvider(child, fTs + numToSkip); |
| 61 | } |
| 62 | numToSkip += (fp.*COUNT)(); |
| 63 | } |
| 64 | SK_ABORT("Didn't find the child." ); |
| 65 | return {nullptr, nullptr}; |
| 66 | } |
| 67 | |
| 68 | private: |
| 69 | const GrFragmentProcessor* fFP; |
| 70 | const T* fTs; |
| 71 | }; |
| 72 | |
| 73 | public: |
| 74 | using TransformedCoordVars = BuilderInputProvider<GrGLSLPrimitiveProcessor::TransformVar, |
| 75 | &GrFragmentProcessor::numCoordTransforms>; |
| 76 | using TextureSamplers = |
| 77 | BuilderInputProvider<SamplerHandle, &GrFragmentProcessor::numTextureSamplers>; |
| 78 | |
| 79 | /** Called when the program stage should insert its code into the shaders. The code in each |
| 80 | shader will be in its own block ({}) and so locally scoped names will not collide across |
| 81 | stages. |
| 82 | |
| 83 | @param fragBuilder Interface used to emit code in the shaders. |
| 84 | @param fp The processor that generated this program stage. |
| 85 | @param key The key that was computed by GenKey() from the generating |
| 86 | GrProcessor. |
| 87 | @param outputColor A predefined half4 in the FS in which the stage should place its |
| 88 | output color (or coverage). |
| 89 | @param inputColor A half4 that holds the input color to the stage in the FS. This may |
| 90 | be nullptr in which case the fInputColor is set to "half4(1.0)" |
| 91 | (solid white) so this is guaranteed non-null. |
| 92 | TODO: Better system for communicating optimization info |
| 93 | (e.g. input color is solid white, trans black, known to be opaque, |
| 94 | etc.) that allows the processor to communicate back similar known |
| 95 | info about its output. |
| 96 | @param transformedCoords Fragment shader variables containing the coords computed using |
| 97 | each of the GrFragmentProcessor's GrCoordTransforms. |
| 98 | @param texSamplers Contains one entry for each TextureSampler of the GrProcessor. |
| 99 | These can be passed to the builder to emit texture reads in the |
| 100 | generated code. |
| 101 | */ |
| 102 | struct EmitArgs { |
| 103 | EmitArgs(GrGLSLFPFragmentBuilder* fragBuilder, |
| 104 | GrGLSLUniformHandler* uniformHandler, |
| 105 | const GrShaderCaps* caps, |
| 106 | const GrFragmentProcessor& fp, |
| 107 | const char* outputColor, |
| 108 | const char* inputColor, |
| 109 | const TransformedCoordVars& transformedCoordVars, |
| 110 | const TextureSamplers& textureSamplers) |
| 111 | : fFragBuilder(fragBuilder) |
| 112 | , fUniformHandler(uniformHandler) |
| 113 | , fShaderCaps(caps) |
| 114 | , fFp(fp) |
| 115 | , fOutputColor(outputColor) |
| 116 | , fInputColor(inputColor ? inputColor : "half4(1.0)" ) |
| 117 | , fTransformedCoords(transformedCoordVars) |
| 118 | , fTexSamplers(textureSamplers) {} |
| 119 | GrGLSLFPFragmentBuilder* fFragBuilder; |
| 120 | GrGLSLUniformHandler* fUniformHandler; |
| 121 | const GrShaderCaps* fShaderCaps; |
| 122 | const GrFragmentProcessor& fFp; |
| 123 | const char* fOutputColor; |
| 124 | const char* fInputColor; |
| 125 | const TransformedCoordVars& fTransformedCoords; |
| 126 | const TextureSamplers& fTexSamplers; |
| 127 | }; |
| 128 | |
| 129 | virtual void emitCode(EmitArgs&) = 0; |
| 130 | |
| 131 | // This does not recurse to any attached child processors. Recursing the entire processor tree |
| 132 | // is the responsibility of the caller. |
| 133 | void setData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor); |
| 134 | |
| 135 | int numChildProcessors() const { return fChildProcessors.count(); } |
| 136 | |
| 137 | GrGLSLFragmentProcessor* childProcessor(int index) const { return fChildProcessors[index]; } |
| 138 | |
| 139 | // Invoke the child with the default input color (solid white) |
| 140 | inline SkString invokeChild(int childIndex, EmitArgs& parentArgs, |
| 141 | SkSL::String skslCoords = "" ) { |
| 142 | return this->invokeChild(childIndex, nullptr, parentArgs, skslCoords); |
| 143 | } |
| 144 | |
| 145 | /** Invokes a child proc in its own scope. Pass in the parent's EmitArgs and invokeChild will |
| 146 | * automatically extract the coords and samplers of that child and pass them on to the child's |
| 147 | * emitCode(). Also, any uniforms or functions emitted by the child will have their names |
| 148 | * mangled to prevent redefinitions. The returned string contains the output color (as a call |
| 149 | * to the child's helper function). It is legal to pass nullptr as inputColor, since all |
| 150 | * fragment processors are required to work without an input color. |
| 151 | */ |
| 152 | SkString invokeChild(int childIndex, const char* inputColor, EmitArgs& parentArgs, |
| 153 | SkSL::String skslCoords = "" ); |
| 154 | |
| 155 | /** |
| 156 | * Pre-order traversal of a GLSLFP hierarchy, or of multiple trees with roots in an array of |
| 157 | * GLSLFPS. If initialized with an array color followed by coverage processors installed in a |
| 158 | * program thenthe iteration order will agree with a GrFragmentProcessor::Iter initialized with |
| 159 | * a GrPipeline that produces the same program key. |
| 160 | */ |
| 161 | class Iter { |
| 162 | public: |
| 163 | Iter(std::unique_ptr<GrGLSLFragmentProcessor> fps[], int cnt); |
| 164 | |
| 165 | GrGLSLFragmentProcessor& operator*() const; |
| 166 | GrGLSLFragmentProcessor* operator->() const; |
| 167 | Iter& operator++(); |
| 168 | operator bool() const { return !fFPStack.empty(); } |
| 169 | |
| 170 | // Because each iterator carries a stack we want to avoid copies. |
| 171 | Iter(const Iter&) = delete; |
| 172 | Iter& operator=(const Iter&) = delete; |
| 173 | |
| 174 | private: |
| 175 | SkSTArray<4, GrGLSLFragmentProcessor*, true> fFPStack; |
| 176 | }; |
| 177 | |
| 178 | protected: |
| 179 | /** A GrGLSLFragmentProcessor instance can be reused with any GrFragmentProcessor that produces |
| 180 | the same stage key; this function reads data from a GrFragmentProcessor and uploads any |
| 181 | uniform variables required by the shaders created in emitCode(). The GrFragmentProcessor |
| 182 | parameter is guaranteed to be of the same type that created this GrGLSLFragmentProcessor and |
| 183 | to have an identical processor key as the one that created this GrGLSLFragmentProcessor. */ |
| 184 | virtual void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) {} |
| 185 | |
| 186 | private: |
| 187 | // one per child; either not present or empty string if not yet emitted |
| 188 | SkTArray<SkString> fFunctionNames; |
| 189 | |
| 190 | SkTArray<GrGLSLFragmentProcessor*, true> fChildProcessors; |
| 191 | |
| 192 | friend class GrFragmentProcessor; |
| 193 | }; |
| 194 | |
| 195 | #endif |
| 196 | |