| wangyix | 6af0c93 | 2015-07-22 10:21:17 -0700 | [diff] [blame] | 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 |  | 
| egdaniel | 64c4728 | 2015-11-13 06:54:19 -0800 | [diff] [blame] | 8 | #ifndef GrGLSLFragmentProcessor_DEFINED | 
 | 9 | #define GrGLSLFragmentProcessor_DEFINED | 
| wangyix | 6af0c93 | 2015-07-22 10:21:17 -0700 | [diff] [blame] | 10 |  | 
| cdalton | 3f6f76f | 2016-04-11 12:18:09 -0700 | [diff] [blame] | 11 | #include "GrFragmentProcessor.h" | 
| bsalomon | 1a1aa93 | 2016-09-12 09:30:36 -0700 | [diff] [blame] | 12 | #include "GrShaderVar.h" | 
| egdaniel | 018fb62 | 2015-10-28 07:26:40 -0700 | [diff] [blame] | 13 | #include "glsl/GrGLSLProgramDataManager.h" | 
| Brian Salomon | f9f4512 | 2016-11-29 11:59:17 -0500 | [diff] [blame] | 14 | #include "glsl/GrGLSLUniformHandler.h" | 
| wangyix | 6af0c93 | 2015-07-22 10:21:17 -0700 | [diff] [blame] | 15 |  | 
| egdaniel | 7dc4bd0 | 2015-10-29 07:57:01 -0700 | [diff] [blame] | 16 | class GrProcessor; | 
 | 17 | class GrProcessorKeyBuilder; | 
| egdaniel | 8dcdedc | 2015-11-11 06:27:20 -0800 | [diff] [blame] | 18 | class GrGLSLFPBuilder; | 
| cdalton | 8528541 | 2016-02-18 12:37:07 -0800 | [diff] [blame] | 19 | class GrGLSLFPFragmentBuilder; | 
| wangyix | 6af0c93 | 2015-07-22 10:21:17 -0700 | [diff] [blame] | 20 |  | 
| egdaniel | 64c4728 | 2015-11-13 06:54:19 -0800 | [diff] [blame] | 21 | class GrGLSLFragmentProcessor { | 
| wangyix | 6af0c93 | 2015-07-22 10:21:17 -0700 | [diff] [blame] | 22 | public: | 
| egdaniel | 64c4728 | 2015-11-13 06:54:19 -0800 | [diff] [blame] | 23 |     GrGLSLFragmentProcessor() {} | 
| wangyix | 6af0c93 | 2015-07-22 10:21:17 -0700 | [diff] [blame] | 24 |  | 
| egdaniel | 64c4728 | 2015-11-13 06:54:19 -0800 | [diff] [blame] | 25 |     virtual ~GrGLSLFragmentProcessor() { | 
| wangyix | b1daa86 | 2015-08-18 11:29:31 -0700 | [diff] [blame] | 26 |         for (int i = 0; i < fChildProcessors.count(); ++i) { | 
| halcanary | 385fe4d | 2015-08-26 13:07:48 -0700 | [diff] [blame] | 27 |             delete fChildProcessors[i]; | 
| wangyix | b1daa86 | 2015-08-18 11:29:31 -0700 | [diff] [blame] | 28 |         } | 
 | 29 |     } | 
| wangyix | 6af0c93 | 2015-07-22 10:21:17 -0700 | [diff] [blame] | 30 |  | 
| Brian Salomon | f9f4512 | 2016-11-29 11:59:17 -0500 | [diff] [blame] | 31 |     using UniformHandle      = GrGLSLUniformHandler::UniformHandle; | 
 | 32 |     using SamplerHandle      = GrGLSLUniformHandler::SamplerHandle; | 
| wangyix | 6af0c93 | 2015-07-22 10:21:17 -0700 | [diff] [blame] | 33 |  | 
| bsalomon | b58a2b4 | 2016-09-26 06:55:02 -0700 | [diff] [blame] | 34 | private: | 
| bsalomon | a624bf3 | 2016-09-20 09:12:47 -0700 | [diff] [blame] | 35 |     /** | 
| bsalomon | b58a2b4 | 2016-09-26 06:55:02 -0700 | [diff] [blame] | 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. | 
| bsalomon | a624bf3 | 2016-09-20 09:12:47 -0700 | [diff] [blame] | 40 |      */ | 
| Brian Salomon | e782f84 | 2018-07-31 13:53:11 -0400 | [diff] [blame] | 41 |     template <typename T, int (GrFragmentProcessor::*COUNT)() const> | 
| bsalomon | b58a2b4 | 2016-09-26 06:55:02 -0700 | [diff] [blame] | 42 |     class BuilderInputProvider { | 
| bsalomon | a624bf3 | 2016-09-20 09:12:47 -0700 | [diff] [blame] | 43 |     public: | 
| bsalomon | b58a2b4 | 2016-09-26 06:55:02 -0700 | [diff] [blame] | 44 |         BuilderInputProvider(const GrFragmentProcessor* fp, const T* ts) : fFP(fp) , fTs(ts) {} | 
| bsalomon | a624bf3 | 2016-09-20 09:12:47 -0700 | [diff] [blame] | 45 |  | 
| bsalomon | b58a2b4 | 2016-09-26 06:55:02 -0700 | [diff] [blame] | 46 |         const T& operator[] (int i) const { | 
 | 47 |             SkASSERT(i >= 0 && i < (fFP->*COUNT)()); | 
 | 48 |             return fTs[i]; | 
| bsalomon | a624bf3 | 2016-09-20 09:12:47 -0700 | [diff] [blame] | 49 |         } | 
 | 50 |  | 
| Robert Phillips | 94ade75 | 2018-10-09 12:32:31 -0400 | [diff] [blame] | 51 |         int count() const { return (fFP->*COUNT)(); } | 
 | 52 |  | 
| bsalomon | b58a2b4 | 2016-09-26 06:55:02 -0700 | [diff] [blame] | 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 |         } | 
| bsalomon | a624bf3 | 2016-09-20 09:12:47 -0700 | [diff] [blame] | 65 |  | 
 | 66 |     private: | 
 | 67 |         const GrFragmentProcessor* fFP; | 
| bsalomon | b58a2b4 | 2016-09-26 06:55:02 -0700 | [diff] [blame] | 68 |         const T*                   fTs; | 
| bsalomon | a624bf3 | 2016-09-20 09:12:47 -0700 | [diff] [blame] | 69 |     }; | 
 | 70 |  | 
| bsalomon | b58a2b4 | 2016-09-26 06:55:02 -0700 | [diff] [blame] | 71 | public: | 
| Brian Salomon | e782f84 | 2018-07-31 13:53:11 -0400 | [diff] [blame] | 72 |     using TransformedCoordVars = | 
 | 73 |             BuilderInputProvider<GrShaderVar, &GrFragmentProcessor::numCoordTransforms>; | 
 | 74 |     using TextureSamplers = | 
 | 75 |             BuilderInputProvider<SamplerHandle, &GrFragmentProcessor::numTextureSamplers>; | 
| bsalomon | b58a2b4 | 2016-09-26 06:55:02 -0700 | [diff] [blame] | 76 |  | 
| wangyix | 6af0c93 | 2015-07-22 10:21:17 -0700 | [diff] [blame] | 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 |  | 
| bsalomon | 1a1aa93 | 2016-09-12 09:30:36 -0700 | [diff] [blame] | 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. | 
| Ethan Nicholas | f7b8820 | 2017-09-18 14:10:39 -0400 | [diff] [blame] | 85 |         @param outputColor       A predefined half4 in the FS in which the stage should place its | 
| bsalomon | 1a1aa93 | 2016-09-12 09:30:36 -0700 | [diff] [blame] | 86 |                                  output color (or coverage). | 
| Ethan Nicholas | f7b8820 | 2017-09-18 14:10:39 -0400 | [diff] [blame] | 87 |         @param inputColor        A half4 that holds the input color to the stage in the FS. This may | 
| Michael Ludwig | 231de03 | 2018-08-30 14:33:01 -0400 | [diff] [blame] | 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 | 
| bsalomon | 1a1aa93 | 2016-09-12 09:30:36 -0700 | [diff] [blame] | 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 | 
| bsalomon | a624bf3 | 2016-09-20 09:12:47 -0700 | [diff] [blame] | 95 |                                  each of the GrFragmentProcessor's GrCoordTransforms. | 
| Brian Salomon | 0bbecb2 | 2016-11-17 11:38:22 -0500 | [diff] [blame] | 96 |         @param texSamplers       Contains one entry for each TextureSampler  of the GrProcessor. | 
| bsalomon | 1a1aa93 | 2016-09-12 09:30:36 -0700 | [diff] [blame] | 97 |                                  These can be passed to the builder to emit texture reads in the | 
 | 98 |                                  generated code. | 
| bsalomon | 38ddbad | 2015-09-24 06:00:00 -0700 | [diff] [blame] | 99 |      */ | 
| wangyix | 7c157a9 | 2015-07-22 15:08:53 -0700 | [diff] [blame] | 100 |     struct EmitArgs { | 
| cdalton | 8528541 | 2016-02-18 12:37:07 -0800 | [diff] [blame] | 101 |         EmitArgs(GrGLSLFPFragmentBuilder* fragBuilder, | 
| egdaniel | 7ea439b | 2015-12-03 09:20:44 -0800 | [diff] [blame] | 102 |                  GrGLSLUniformHandler* uniformHandler, | 
| Brian Salomon | 94efbf5 | 2016-11-29 13:43:05 -0500 | [diff] [blame] | 103 |                  const GrShaderCaps* caps, | 
| wangyix | 7c157a9 | 2015-07-22 15:08:53 -0700 | [diff] [blame] | 104 |                  const GrFragmentProcessor& fp, | 
 | 105 |                  const char* outputColor, | 
 | 106 |                  const char* inputColor, | 
| bsalomon | a624bf3 | 2016-09-20 09:12:47 -0700 | [diff] [blame] | 107 |                  const TransformedCoordVars& transformedCoordVars, | 
| Brian Salomon | 662ea4b | 2018-07-12 14:53:49 -0400 | [diff] [blame] | 108 |                  const TextureSamplers& textureSamplers) | 
| Brian Salomon | e23bffd | 2017-06-02 11:01:10 -0400 | [diff] [blame] | 109 |                 : fFragBuilder(fragBuilder) | 
 | 110 |                 , fUniformHandler(uniformHandler) | 
 | 111 |                 , fShaderCaps(caps) | 
 | 112 |                 , fFp(fp) | 
 | 113 |                 , fOutputColor(outputColor) | 
| Michael Ludwig | 231de03 | 2018-08-30 14:33:01 -0400 | [diff] [blame] | 114 |                 , fInputColor(inputColor ? inputColor : "half4(1.0)") | 
| Brian Salomon | e23bffd | 2017-06-02 11:01:10 -0400 | [diff] [blame] | 115 |                 , fTransformedCoords(transformedCoordVars) | 
| Brian Salomon | 662ea4b | 2018-07-12 14:53:49 -0400 | [diff] [blame] | 116 |                 , fTexSamplers(textureSamplers) {} | 
| cdalton | 8528541 | 2016-02-18 12:37:07 -0800 | [diff] [blame] | 117 |         GrGLSLFPFragmentBuilder* fFragBuilder; | 
| egdaniel | 7ea439b | 2015-12-03 09:20:44 -0800 | [diff] [blame] | 118 |         GrGLSLUniformHandler* fUniformHandler; | 
| Brian Salomon | 1edc5b9 | 2016-11-29 13:43:46 -0500 | [diff] [blame] | 119 |         const GrShaderCaps* fShaderCaps; | 
| wangyix | 7c157a9 | 2015-07-22 15:08:53 -0700 | [diff] [blame] | 120 |         const GrFragmentProcessor& fFp; | 
 | 121 |         const char* fOutputColor; | 
 | 122 |         const char* fInputColor; | 
| bsalomon | a624bf3 | 2016-09-20 09:12:47 -0700 | [diff] [blame] | 123 |         const TransformedCoordVars& fTransformedCoords; | 
| bsalomon | b58a2b4 | 2016-09-26 06:55:02 -0700 | [diff] [blame] | 124 |         const TextureSamplers& fTexSamplers; | 
| wangyix | 7c157a9 | 2015-07-22 15:08:53 -0700 | [diff] [blame] | 125 |     }; | 
 | 126 |  | 
 | 127 |     virtual void emitCode(EmitArgs&) = 0; | 
| wangyix | 6af0c93 | 2015-07-22 10:21:17 -0700 | [diff] [blame] | 128 |  | 
| Michael Ludwig | d3a357d | 2018-09-27 17:31:08 -0400 | [diff] [blame] | 129 |     // This does not recurse to any attached child processors. Recursing the entire processor tree | 
 | 130 |     // is the responsibility of the caller. | 
| egdaniel | 018fb62 | 2015-10-28 07:26:40 -0700 | [diff] [blame] | 131 |     void setData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor); | 
| wangyix | 6af0c93 | 2015-07-22 10:21:17 -0700 | [diff] [blame] | 132 |  | 
| wangyix | b1daa86 | 2015-08-18 11:29:31 -0700 | [diff] [blame] | 133 |     int numChildProcessors() const { return fChildProcessors.count(); } | 
 | 134 |  | 
| bsalomon | b58a2b4 | 2016-09-26 06:55:02 -0700 | [diff] [blame] | 135 |     GrGLSLFragmentProcessor* childProcessor(int index) { | 
| wangyix | b1daa86 | 2015-08-18 11:29:31 -0700 | [diff] [blame] | 136 |         return fChildProcessors[index]; | 
 | 137 |     } | 
 | 138 |  | 
| Michael Ludwig | 231de03 | 2018-08-30 14:33:01 -0400 | [diff] [blame] | 139 |     // Emit the child with the default input color (solid white) | 
| Ethan Nicholas | 2983f40 | 2017-05-08 09:36:08 -0400 | [diff] [blame] | 140 |     inline void emitChild(int childIndex, SkString* outputColor, EmitArgs& parentArgs) { | 
| Michael Ludwig | 231de03 | 2018-08-30 14:33:01 -0400 | [diff] [blame] | 141 |         this->emitChild(childIndex, nullptr, outputColor, parentArgs); | 
| Ethan Nicholas | 2983f40 | 2017-05-08 09:36:08 -0400 | [diff] [blame] | 142 |     } | 
 | 143 |  | 
| wangyix | 54a6b1a | 2015-09-08 08:41:51 -0700 | [diff] [blame] | 144 |     /** Will emit the code of a child proc in its own scope. Pass in the parent's EmitArgs and | 
| bsalomon | 38ddbad | 2015-09-24 06:00:00 -0700 | [diff] [blame] | 145 |      *  emitChild will automatically extract the coords and samplers of that child and pass them | 
 | 146 |      *  on to the child's emitCode(). Also, any uniforms or functions emitted by the child will | 
 | 147 |      *  have their names mangled to prevent redefinitions. The output color name is also mangled | 
 | 148 |      *  therefore in an in/out param. It will be declared in mangled form by emitChild(). It is | 
 | 149 |      *  legal to pass nullptr as inputColor, since all fragment processors are required to work | 
 | 150 |      *  without an input color. | 
| wangyix | 54a6b1a | 2015-09-08 08:41:51 -0700 | [diff] [blame] | 151 |      */ | 
| bsalomon | 38ddbad | 2015-09-24 06:00:00 -0700 | [diff] [blame] | 152 |     void emitChild(int childIndex, const char* inputColor, SkString* outputColor, | 
 | 153 |                    EmitArgs& parentArgs); | 
 | 154 |  | 
| Michael Ludwig | 231de03 | 2018-08-30 14:33:01 -0400 | [diff] [blame] | 155 |     // Use the parent's output color to hold child's output, and use the | 
 | 156 |     // default input color of solid white | 
| Ethan Nicholas | 2983f40 | 2017-05-08 09:36:08 -0400 | [diff] [blame] | 157 |     inline void emitChild(int childIndex, EmitArgs& args) { | 
| Michael Ludwig | 231de03 | 2018-08-30 14:33:01 -0400 | [diff] [blame] | 158 |         // null pointer cast required to disambiguate the function call | 
 | 159 |         this->emitChild(childIndex, (const char*) nullptr, args); | 
| Ethan Nicholas | 2983f40 | 2017-05-08 09:36:08 -0400 | [diff] [blame] | 160 |     } | 
 | 161 |  | 
| bsalomon | 38ddbad | 2015-09-24 06:00:00 -0700 | [diff] [blame] | 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); | 
| wangyix | 2a37843 | 2015-08-18 12:00:12 -0700 | [diff] [blame] | 164 |  | 
| bsalomon | b58a2b4 | 2016-09-26 06:55:02 -0700 | [diff] [blame] | 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); } | 
| Brian Salomon | 4d3f517 | 2018-06-07 14:42:52 -0400 | [diff] [blame] | 172 |         explicit Iter(std::unique_ptr<GrGLSLFragmentProcessor> fps[], int cnt) { | 
| bsalomon | b58a2b4 | 2016-09-26 06:55:02 -0700 | [diff] [blame] | 173 |             for (int i = cnt - 1; i >= 0; --i) { | 
| Brian Salomon | 4d3f517 | 2018-06-07 14:42:52 -0400 | [diff] [blame] | 174 |                 fFPStack.push_back(fps[i].get()); | 
| bsalomon | b58a2b4 | 2016-09-26 06:55:02 -0700 | [diff] [blame] | 175 |             } | 
 | 176 |         } | 
 | 177 |         GrGLSLFragmentProcessor* next(); | 
 | 178 |  | 
 | 179 |     private: | 
 | 180 |         SkSTArray<4, GrGLSLFragmentProcessor*, true> fFPStack; | 
 | 181 |     }; | 
 | 182 |  | 
| wangyix | b1daa86 | 2015-08-18 11:29:31 -0700 | [diff] [blame] | 183 | protected: | 
| egdaniel | 64c4728 | 2015-11-13 06:54:19 -0800 | [diff] [blame] | 184 |     /** A GrGLSLFragmentProcessor instance can be reused with any GrFragmentProcessor that produces | 
| wangyix | b1daa86 | 2015-08-18 11:29:31 -0700 | [diff] [blame] | 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 | 
| egdaniel | 64c4728 | 2015-11-13 06:54:19 -0800 | [diff] [blame] | 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.  */ | 
| Brian Salomon | ab015ef | 2017-04-04 10:15:51 -0400 | [diff] [blame] | 189 |     virtual void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) {} | 
| wangyix | b1daa86 | 2015-08-18 11:29:31 -0700 | [diff] [blame] | 190 |  | 
| wangyix | 6af0c93 | 2015-07-22 10:21:17 -0700 | [diff] [blame] | 191 | private: | 
| bsalomon | 38ddbad | 2015-09-24 06:00:00 -0700 | [diff] [blame] | 192 |     void internalEmitChild(int, const char*, const char*, EmitArgs&); | 
 | 193 |  | 
| egdaniel | 64c4728 | 2015-11-13 06:54:19 -0800 | [diff] [blame] | 194 |     SkTArray<GrGLSLFragmentProcessor*, true> fChildProcessors; | 
| wangyix | b1daa86 | 2015-08-18 11:29:31 -0700 | [diff] [blame] | 195 |  | 
 | 196 |     friend class GrFragmentProcessor; | 
| wangyix | 6af0c93 | 2015-07-22 10:21:17 -0700 | [diff] [blame] | 197 | }; | 
 | 198 |  | 
 | 199 | #endif |