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 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:
     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 
     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 {
    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 
    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
    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