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 ImageStorageHandle = GrGLSLUniformHandler::ImageStorageHandle;
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, 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 {
112        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
151    static void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*) {}
152
153    int numChildProcessors() const { return fChildProcessors.count(); }
154
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:
179        explicit Iter(GrGLSLFragmentProcessor* fp) { fFPStack.push_back(fp); }
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
191protected:
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
198    virtual void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) {}
199
200private:
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