Home | History | Annotate | Download | only in glsl
      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:
     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 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:
     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         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 {
    110         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 
    146     static void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*) {}
    147 
    148     int numChildProcessors() const { return fChildProcessors.count(); }
    149 
    150     GrGLSLFragmentProcessor* childProcessor(int index) {
    151         return fChildProcessors[index];
    152     }
    153 
    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 
    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:
    182         explicit Iter(GrGLSLFragmentProcessor* fp) { fFPStack.push_back(fp); }
    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.  */
    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