/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef GrGLShaderBuilder_DEFINED
#define GrGLShaderBuilder_DEFINED

#include "GrAllocator.h"
#include "GrBackendEffectFactory.h"
#include "GrColor.h"
#include "GrEffect.h"
#include "SkTypes.h"
#include "gl/GrGLProgramDesc.h"
#include "gl/GrGLProgramEffects.h"
#include "gl/GrGLSL.h"
#include "gl/GrGLProgramDataManager.h"

#include <stdarg.h>

class GrGLContextInfo;
class GrEffectStage;
class GrGLProgramDesc;

/**
  Contains all the incremental state of a shader as it is being built,as well as helpers to
  manipulate that state.
*/
class GrGLShaderBuilder {
public:
    typedef GrTAllocator<GrGLShaderVar> VarArray;
    typedef GrGLProgramEffects::TextureSampler TextureSampler;
    typedef GrGLProgramEffects::TransformedCoordsArray TransformedCoordsArray;
    typedef GrGLProgramDataManager::BuilderUniform BuilderUniform;

    enum ShaderVisibility {
        kVertex_Visibility   = 0x1,
        kGeometry_Visibility = 0x2,
        kFragment_Visibility = 0x4,
    };

    typedef GrGLProgramDataManager::UniformHandle UniformHandle;

    // Handles for program uniforms (other than per-effect uniforms)
    struct UniformHandles {
        UniformHandle       fViewMatrixUni;
        UniformHandle       fRTAdjustmentUni;
        UniformHandle       fColorUni;
        UniformHandle       fCoverageUni;

        // We use the render target height to provide a y-down frag coord when specifying
        // origin_upper_left is not supported.
        UniformHandle       fRTHeightUni;

        // Uniforms for computing texture coords to do the dst-copy lookup
        UniformHandle       fDstCopyTopLeftUni;
        UniformHandle       fDstCopyScaleUni;
        UniformHandle       fDstCopySamplerUni;
    };

    struct GenProgramOutput {
        GenProgramOutput()
            : fColorEffects(NULL)
            , fCoverageEffects(NULL)
            , fHasVertexShader(false)
            , fTexCoordSetCnt(0)
            , fProgramID(0) {}

        GenProgramOutput(const GenProgramOutput& other) {
            *this = other;
        }

        GenProgramOutput& operator=(const GenProgramOutput& other) {
            fColorEffects.reset(SkRef(other.fColorEffects.get()));
            fCoverageEffects.reset(SkRef(other.fCoverageEffects.get()));
            fUniformHandles = other.fUniformHandles;
            fHasVertexShader = other.fHasVertexShader;
            fTexCoordSetCnt = other.fTexCoordSetCnt;
            fProgramID = other.fProgramID;
            return *this;
        }

        SkAutoTUnref<GrGLProgramEffects> fColorEffects;
        SkAutoTUnref<GrGLProgramEffects> fCoverageEffects;
        UniformHandles                   fUniformHandles;
        bool                             fHasVertexShader;
        int                              fTexCoordSetCnt;
        GrGLuint                         fProgramID;
    };

    static bool GenProgram(GrGpuGL* gpu,
                           GrGLProgramDataManager* pdman,
                           const GrGLProgramDesc& desc,
                           const GrEffectStage* inColorStages[],
                           const GrEffectStage* inCoverageStages[],
                           GenProgramOutput* output);

    virtual ~GrGLShaderBuilder() {}

    /**
     * Use of these features may require a GLSL extension to be enabled. Shaders may not compile
     * if code is added that uses one of these features without calling enableFeature()
     */
    enum GLSLFeature {
        kStandardDerivatives_GLSLFeature = 0,

        kLastGLSLFeature = kStandardDerivatives_GLSLFeature
    };

    /**
     * If the feature is supported then true is returned and any necessary #extension declarations
     * are added to the shaders. If the feature is not supported then false will be returned.
     */
    bool enableFeature(GLSLFeature);

    /**
     * Called by GrGLEffects to add code the fragment shader.
     */
    void fsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
        va_list args;
        va_start(args, format);
        fFSCode.appendVAList(format, args);
        va_end(args);
    }

    void fsCodeAppend(const char* str) { fFSCode.append(str); }

    /** Appends a 2D texture sample with projection if necessary. coordType must either be Vec2f or
        Vec3f. The latter is interpreted as projective texture coords. The vec length and swizzle
        order of the result depends on the GrTextureAccess associated with the TextureSampler. */
    void appendTextureLookup(SkString* out,
                             const TextureSampler&,
                             const char* coordName,
                             GrSLType coordType = kVec2f_GrSLType) const;

    /** Version of above that appends the result to the fragment shader code instead.*/
    void fsAppendTextureLookup(const TextureSampler&,
                               const char* coordName,
                               GrSLType coordType = kVec2f_GrSLType);


    /** Does the work of appendTextureLookup and modulates the result by modulation. The result is
        always a vec4. modulation and the swizzle specified by TextureSampler must both be vec4 or
        float. If modulation is "" or NULL it this function acts as though appendTextureLookup were
        called. */
    void fsAppendTextureLookupAndModulate(const char* modulation,
                                          const TextureSampler&,
                                          const char* coordName,
                                          GrSLType coordType = kVec2f_GrSLType);

    /** Emits a helper function outside of main() in the fragment shader. */
    void fsEmitFunction(GrSLType returnType,
                        const char* name,
                        int argCnt,
                        const GrGLShaderVar* args,
                        const char* body,
                        SkString* outName);

    typedef uint8_t DstReadKey;
    typedef uint8_t FragPosKey;

    /**  Returns a key for adding code to read the copy-of-dst color in service of effects that
         require reading the dst. It must not return 0 because 0 indicates that there is no dst
         copy read at all (in which case this function should not be called). */
    static DstReadKey KeyForDstRead(const GrTexture* dstCopy, const GrGLCaps&);

    /** Returns a key for reading the fragment location. This should only be called if there is an
        effect that will requires the fragment position. If the fragment position is not required,
        the key is 0. */
    static FragPosKey KeyForFragmentPosition(const GrRenderTarget* dst, const GrGLCaps&);

    /** If texture swizzling is available using tex parameters then it is preferred over mangling
        the generated shader code. This potentially allows greater reuse of cached shaders. */
    static const GrGLenum* GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps);

    /** Add a uniform variable to the current program, that has visibility in one or more shaders.
        visibility is a bitfield of ShaderVisibility values indicating from which shaders the
        uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
        supported at this time. The actual uniform name will be mangled. If outName is not NULL then
        it will refer to the final uniform name after return. Use the addUniformArray variant to add
        an array of uniforms. */
    GrGLProgramDataManager::UniformHandle addUniform(uint32_t visibility,
                                                     GrSLType type,
                                                     const char* name,
                                                     const char** outName = NULL) {
        return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
    }
    GrGLProgramDataManager::UniformHandle addUniformArray(uint32_t visibility,
                                                          GrSLType type,
                                                          const char* name,
                                                          int arrayCount,
                                                          const char** outName = NULL);

    const GrGLShaderVar& getUniformVariable(GrGLProgramDataManager::UniformHandle u) const {
        return fProgramDataManager->getBuilderUniform(fUniforms, u).fVariable;
    }

    /**
     * Shortcut for getUniformVariable(u).c_str()
     */
    const char* getUniformCStr(GrGLProgramDataManager::UniformHandle u) const {
        return this->getUniformVariable(u).c_str();
    }

    /**
     * This returns a variable name to access the 2D, perspective correct version of the coords in
     * the fragment shader. If the coordinates at index are 3-dimensional, it immediately emits a
     * perspective divide into the fragment shader (xy / z) to convert them to 2D.
     */
    SkString ensureFSCoords2D(const TransformedCoordsArray&, int index);

    /** Returns a variable name that represents the position of the fragment in the FS. The position
        is in device space (e.g. 0,0 is the top left and pixel centers are at half-integers). */
    const char* fragmentPosition();

    /** Returns the variable name that holds the color of the destination pixel. This may be NULL if
        no effect advertised that it will read the destination. */
    const char* dstColor();

    const GrGLContextInfo& ctxInfo() const;

    /**
     * Helper for begining and ending a block in the fragment code. TODO: Make GrGLShaderBuilder
     * aware of all blocks and turn single \t's into the correct number of tabs (or spaces) so that
     * our shaders print pretty without effect writers tracking indentation.
     */
    class FSBlock {
    public:
        FSBlock(GrGLShaderBuilder* builder) : fBuilder(builder) {
            SkASSERT(NULL != builder);
            fBuilder->fsCodeAppend("\t{\n");
        }

        ~FSBlock() {
            fBuilder->fsCodeAppend("\t}\n");
        }
    private:
        GrGLShaderBuilder* fBuilder;
    };

protected:
    GrGLShaderBuilder(GrGpuGL*, GrGLProgramDataManager*, const GrGLProgramDesc&);

    GrGpuGL* gpu() const { return fGpu; }

    const GrGLProgramDesc& desc() const { return fDesc; }

    /** Add input/output variable declarations (i.e. 'varying') to the fragment shader. */
    GrGLShaderVar& fsInputAppend() { return fFSInputs.push_back(); }

    // Helper for emitEffects().
    void createAndEmitEffects(GrGLProgramEffectsBuilder*,
                              const GrEffectStage* effectStages[],
                              int effectCnt,
                              const GrGLProgramDesc::EffectKeyProvider&,
                              GrGLSLExpr4* inOutFSColor);

    // Generates a name for a variable. The generated string will be name prefixed by the prefix
    // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
    // generating stage code.
    void nameVariable(SkString* out, char prefix, const char* name);

    virtual bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;

    virtual void bindProgramLocations(GrGLuint programId) const;

    void appendDecls(const VarArray&, SkString*) const;
    void appendUniformDecls(ShaderVisibility, SkString*) const;

    const GenProgramOutput& getOutput() const { return fOutput; }

    GenProgramOutput fOutput;

private:
    class CodeStage : SkNoncopyable {
    public:
        CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffectStage(NULL) {}

        bool inStageCode() const {
            this->validate();
            return NULL != fEffectStage;
        }

        const GrEffectStage* effectStage() const {
            this->validate();
            return fEffectStage;
        }

        int stageIndex() const {
            this->validate();
            return fCurrentIndex;
        }

        class AutoStageRestore : SkNoncopyable {
        public:
            AutoStageRestore(CodeStage* codeStage, const GrEffectStage* newStage) {
                SkASSERT(NULL != codeStage);
                fSavedIndex = codeStage->fCurrentIndex;
                fSavedEffectStage = codeStage->fEffectStage;

                if (NULL == newStage) {
                    codeStage->fCurrentIndex = -1;
                } else {
                    codeStage->fCurrentIndex = codeStage->fNextIndex++;
                }
                codeStage->fEffectStage = newStage;

                fCodeStage = codeStage;
            }
            ~AutoStageRestore() {
                fCodeStage->fCurrentIndex = fSavedIndex;
                fCodeStage->fEffectStage = fSavedEffectStage;
            }
        private:
            CodeStage*              fCodeStage;
            int                     fSavedIndex;
            const GrEffectStage*    fSavedEffectStage;
        };
    private:
        void validate() const { SkASSERT((NULL == fEffectStage) == (-1 == fCurrentIndex)); }
        int                     fNextIndex;
        int                     fCurrentIndex;
        const GrEffectStage*    fEffectStage;
    } fCodeStage;

    bool genProgram(const GrEffectStage* colorStages[], const GrEffectStage* coverageStages[]);

    /**
     * The base class will emit the fragment code that precedes the per-effect code and then call
     * this function. The subclass can use it to insert additional fragment code that should
     * execute before the effects' code and/or emit other shaders (e.g. geometry, vertex).
     *
     * The subclass can modify the initial color or coverage 
     */
    virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) = 0;

    /**
    * Adds code for effects and returns a GrGLProgramEffects* object. The caller is responsible for
    * deleting it when finished. effectStages contains the effects to add. The effect key provider 
    * is used to communicate the key each effect created in its GenKey function. inOutFSColor
    * specifies the input color to the first stage and is updated to be the output color of the
    * last stage. The handles to texture samplers for effectStage[i] are added to
    * effectSamplerHandles[i].
    */
    virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
                                                     int effectCnt,
                                                     const GrGLProgramDesc::EffectKeyProvider&,
                                                     GrGLSLExpr4* inOutFSColor) = 0;

    /**
     * Similar to emitCodeBeforeEffects() but called after per-effect code is emitted.
     */
    virtual void emitCodeAfterEffects() = 0;

    /** Enables using the secondary color output and returns the name of the var in which it is
        to be stored */
    const char* enableSecondaryOutput();
    /** Gets the name of the primary color output. */
    const char* getColorOutputName() const;

    /**
     * Compiles all the shaders, links them into a program, and writes the program id to the output
     * struct.
     **/
    bool finish();

    /**
     * Features that should only be enabled by GrGLShaderBuilder itself.
     */
    enum GLSLPrivateFeature {
        kFragCoordConventions_GLSLPrivateFeature = kLastGLSLFeature + 1,
        kEXTShaderFramebufferFetch_GLSLPrivateFeature,
        kNVShaderFramebufferFetch_GLSLPrivateFeature,
    };
    bool enablePrivateFeature(GLSLPrivateFeature);

    // If we ever have VS/GS features we can expand this to take a bitmask of ShaderVisibility and
    // track the enables separately for each shader.
    void addFSFeature(uint32_t featureBit, const char* extensionName);

    // Interpretation of DstReadKey when generating code
    enum {
        kNoDstRead_DstReadKey           = 0,
        kYesDstRead_DstReadKeyBit       = 0x1, // Set if we do a dst-copy-read.
        kUseAlphaConfig_DstReadKeyBit   = 0x2, // Set if dst-copy config is alpha only.
        kTopLeftOrigin_DstReadKeyBit    = 0x4, // Set if dst-copy origin is top-left.
    };

    enum {
        kNoFragPosRead_FragPosKey           = 0,  // The fragment positition will not be needed.
        kTopLeftFragPosRead_FragPosKey      = 0x1,// Read frag pos relative to top-left.
        kBottomLeftFragPosRead_FragPosKey   = 0x2,// Read frag pos relative to bottom-left.
    };

    const GrGLProgramDesc&                  fDesc;
    GrGpuGL*                                fGpu;
    SkAutoTUnref<GrGLProgramDataManager>    fProgramDataManager;
    uint32_t                                fFSFeaturesAddedMask;
    SkString                                fFSFunctions;
    SkString                                fFSExtensions;
    VarArray                                fFSInputs;
    VarArray                                fFSOutputs;
    GrGLProgramDataManager::BuilderUniformArray fUniforms;

    SkString                                fFSCode;

    bool                                    fSetupFragPosition;
    bool                                    fTopLeftFragPosRead;

    bool                                    fHasCustomColorOutput;
    bool                                    fHasSecondaryOutput;
};

////////////////////////////////////////////////////////////////////////////////

class GrGLFullShaderBuilder : public GrGLShaderBuilder {
public:
    GrGLFullShaderBuilder(GrGpuGL*, GrGLProgramDataManager*, const GrGLProgramDesc&);

    /**
     * Called by GrGLEffects to add code to one of the shaders.
     */
    void vsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
        va_list args;
        va_start(args, format);
        fVSCode.appendVAList(format, args);
        va_end(args);
    }

    void vsCodeAppend(const char* str) { fVSCode.append(str); }

   /** Add a vertex attribute to the current program that is passed in from the vertex data.
       Returns false if the attribute was already there, true otherwise. */
    bool addAttribute(GrSLType type, const char* name);

   /** Add a varying variable to the current program to pass values between vertex and fragment
        shaders. If the last two parameters are non-NULL, they are filled in with the name
        generated. */
    void addVarying(GrSLType type,
                    const char* name,
                    const char** vsOutName = NULL,
                    const char** fsInName = NULL);

    /** Returns a vertex attribute that represents the vertex position in the VS. This is the
        pre-matrix position and is commonly used by effects to compute texture coords via a matrix.
      */
    const GrGLShaderVar& positionAttribute() const { return *fPositionVar; }

    /** Returns a vertex attribute that represents the local coords in the VS. This may be the same
        as positionAttribute() or it may not be. It depends upon whether the rendering code
        specified explicit local coords or not in the GrDrawState. */
    const GrGLShaderVar& localCoordsAttribute() const { return *fLocalCoordsVar; }

    /**
     * Are explicit local coordinates provided as input to the vertex shader.
     */
    bool hasExplicitLocalCoords() const { return (fLocalCoordsVar != fPositionVar); }

    bool addEffectAttribute(int attributeIndex, GrSLType type, const SkString& name);
    const SkString* getEffectAttributeName(int attributeIndex) const;

private:
    virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) SK_OVERRIDE;

    virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
                                                     int effectCnt,
                                                     const GrGLProgramDesc::EffectKeyProvider&,
                                                     GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;

    virtual void emitCodeAfterEffects() SK_OVERRIDE;

    virtual bool compileAndAttachShaders(GrGLuint programId,
                                         SkTDArray<GrGLuint>* shaderIds) const SK_OVERRIDE;

    virtual void bindProgramLocations(GrGLuint programId) const SK_OVERRIDE;

    VarArray                            fVSAttrs;
    VarArray                            fVSOutputs;
    VarArray                            fGSInputs;
    VarArray                            fGSOutputs;

    SkString                            fVSCode;

    struct AttributePair {
        void set(int index, const SkString& name) {
            fIndex = index; fName = name;
        }
        int      fIndex;
        SkString fName;
    };
    SkSTArray<10, AttributePair, true>  fEffectAttributes;

    GrGLShaderVar*                      fPositionVar;
    GrGLShaderVar*                      fLocalCoordsVar;

    typedef GrGLShaderBuilder INHERITED;
};

////////////////////////////////////////////////////////////////////////////////

class GrGLFragmentOnlyShaderBuilder : public GrGLShaderBuilder {
public:
    GrGLFragmentOnlyShaderBuilder(GrGpuGL*, GrGLProgramDataManager*, const GrGLProgramDesc&);

    int addTexCoordSets(int count);

private:
    virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) SK_OVERRIDE {}

    virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
                                                     int effectCnt,
                                                     const GrGLProgramDesc::EffectKeyProvider&,
                                                     GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;

    virtual void emitCodeAfterEffects() SK_OVERRIDE {}

    typedef GrGLShaderBuilder INHERITED;
};

#endif
