• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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     using TexelBufferHandle  = GrGLSLUniformHandler::TexelBufferHandle;
34     using ImageStorageHandle = GrGLSLUniformHandler::ImageStorageHandle;
35 
36 private:
37     /**
38      * This class allows the shader builder to provide each GrGLSLFragmentProcesor 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, typename FPBASE, int (FPBASE::*COUNT)() const>
44     class BuilderInputProvider {
45     public:
BuilderInputProvider(const GrFragmentProcessor * fp,const T * ts)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 
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 = BuilderInputProvider<GrShaderVar, GrFragmentProcessor,
73                                                       &GrFragmentProcessor::numCoordTransforms>;
74     using TextureSamplers = BuilderInputProvider<SamplerHandle, GrResourceIOProcessor,
75                                                  &GrResourceIOProcessor::numTextureSamplers>;
76     using TexelBuffers = BuilderInputProvider<TexelBufferHandle, GrResourceIOProcessor,
77                                                 &GrResourceIOProcessor::numBuffers>;
78     using ImageStorages = BuilderInputProvider<ImageStorageHandle, GrResourceIOProcessor,
79                                                &GrResourceIOProcessor::numImageStorages>;
80 
81     /** Called when the program stage should insert its code into the shaders. The code in each
82         shader will be in its own block ({}) and so locally scoped names will not collide across
83         stages.
84 
85         @param fragBuilder       Interface used to emit code in the shaders.
86         @param fp                The processor that generated this program stage.
87         @param key               The key that was computed by GenKey() from the generating
88                                  GrProcessor.
89         @param outputColor       A predefined vec4 in the FS in which the stage should place its
90                                  output color (or coverage).
91         @param inputColor        A vec4 that holds the input color to the stage in the FS. This may
92                                  be nullptr in which case the implied input is solid white (all
93                                  ones). TODO: Better system for communicating optimization info
94                                  (e.g. input color is solid white, trans black, known to be opaque,
95                                  etc.) that allows the processor to communicate back similar known
96                                  info about its output.
97         @param transformedCoords Fragment shader variables containing the coords computed using
98                                  each of the GrFragmentProcessor's GrCoordTransforms.
99         @param texSamplers       Contains one entry for each TextureSampler  of the GrProcessor.
100                                  These can be passed to the builder to emit texture reads in the
101                                  generated code.
102         @param bufferSamplers    Contains one entry for each BufferAccess of the GrProcessor. These
103                                  can be passed to the builder to emit buffer reads in the generated
104                                  code.
105         @param imageStorages     Contains one entry for each ImageStorageAccess of the GrProcessor.
106                                  These can be passed to the builder to emit image loads and stores
107                                  in the generated code.
108      */
109     struct EmitArgs {
EmitArgsEmitArgs110         EmitArgs(GrGLSLFPFragmentBuilder* fragBuilder,
111                  GrGLSLUniformHandler* uniformHandler,
112                  const GrShaderCaps* caps,
113                  const GrFragmentProcessor& fp,
114                  const char* outputColor,
115                  const char* inputColor,
116                  const TransformedCoordVars& transformedCoordVars,
117                  const TextureSamplers& textureSamplers,
118                  const TexelBuffers& texelBuffers,
119                  const ImageStorages& imageStorages)
120                 : fFragBuilder(fragBuilder)
121                 , fUniformHandler(uniformHandler)
122                 , fShaderCaps(caps)
123                 , fFp(fp)
124                 , fOutputColor(outputColor)
125                 , fInputColor(inputColor)
126                 , fTransformedCoords(transformedCoordVars)
127                 , fTexSamplers(textureSamplers)
128                 , fTexelBuffers(texelBuffers)
129                 , fImageStorages(imageStorages) {}
130         GrGLSLFPFragmentBuilder* fFragBuilder;
131         GrGLSLUniformHandler* fUniformHandler;
132         const GrShaderCaps* fShaderCaps;
133         const GrFragmentProcessor& fFp;
134         const char* fOutputColor;
135         const char* fInputColor;
136         const TransformedCoordVars& fTransformedCoords;
137         const TextureSamplers& fTexSamplers;
138         const TexelBuffers& fTexelBuffers;
139         const ImageStorages& fImageStorages;
140     };
141 
142     virtual void emitCode(EmitArgs&) = 0;
143 
144     void setData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor);
145 
GenKey(const GrProcessor &,const GrShaderCaps &,GrProcessorKeyBuilder *)146     static void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*) {}
147 
numChildProcessors()148     int numChildProcessors() const { return fChildProcessors.count(); }
149 
childProcessor(int index)150     GrGLSLFragmentProcessor* childProcessor(int index) {
151         return fChildProcessors[index];
152     }
153 
emitChild(int childIndex,SkString * outputColor,EmitArgs & parentArgs)154     inline void emitChild(int childIndex, SkString* outputColor, EmitArgs& parentArgs) {
155         this->emitChild(childIndex, "vec4(1.0)", outputColor, parentArgs);
156     }
157 
158     /** Will emit the code of a child proc in its own scope. Pass in the parent's EmitArgs and
159      *  emitChild will automatically extract the coords and samplers of that child and pass them
160      *  on to the child's emitCode(). Also, any uniforms or functions emitted by the child will
161      *  have their names mangled to prevent redefinitions. The output color name is also mangled
162      *  therefore in an in/out param. It will be declared in mangled form by emitChild(). It is
163      *  legal to pass nullptr as inputColor, since all fragment processors are required to work
164      *  without an input color.
165      */
166     void emitChild(int childIndex, const char* inputColor, SkString* outputColor,
167                    EmitArgs& parentArgs);
168 
emitChild(int childIndex,EmitArgs & args)169     inline void emitChild(int childIndex, EmitArgs& args) {
170         this->emitChild(childIndex, "vec4(1.0)", args);
171     }
172 
173     /** Variation that uses the parent's output color variable to hold the child's output.*/
174     void emitChild(int childIndex, const char* inputColor, EmitArgs& parentArgs);
175 
176     /**
177      * Pre-order traversal of a GLSLFP hierarchy, or of multiple trees with roots in an array of
178      * GLSLFPS. This agrees with the traversal order of GrFragmentProcessor::Iter
179      */
180     class Iter : public SkNoncopyable {
181     public:
Iter(GrGLSLFragmentProcessor * fp)182         explicit Iter(GrGLSLFragmentProcessor* fp) { fFPStack.push_back(fp); }
Iter(GrGLSLFragmentProcessor * fps[],int cnt)183         explicit Iter(GrGLSLFragmentProcessor* fps[], int cnt) {
184             for (int i = cnt - 1; i >= 0; --i) {
185                 fFPStack.push_back(fps[i]);
186             }
187         }
188         GrGLSLFragmentProcessor* next();
189 
190     private:
191         SkSTArray<4, GrGLSLFragmentProcessor*, true> fFPStack;
192     };
193 
194 protected:
195     /** A GrGLSLFragmentProcessor instance can be reused with any GrFragmentProcessor that produces
196     the same stage key; this function reads data from a GrFragmentProcessor and uploads any
197     uniform variables required by the shaders created in emitCode(). The GrFragmentProcessor
198     parameter is guaranteed to be of the same type that created this GrGLSLFragmentProcessor and
199     to have an identical processor key as the one that created this GrGLSLFragmentProcessor.  */
onSetData(const GrGLSLProgramDataManager &,const GrFragmentProcessor &)200     virtual void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) {}
201 
202 private:
203     void internalEmitChild(int, const char*, const char*, EmitArgs&);
204 
205     SkTArray<GrGLSLFragmentProcessor*, true> fChildProcessors;
206 
207     friend class GrFragmentProcessor;
208 };
209 
210 #endif
211