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