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

#ifndef GrGLFragmentShaderBuilder_DEFINED
#define GrGLFragmentShaderBuilder_DEFINED

#include "GrGLShaderBuilder.h"

class GrGLVarying;

/*
 * This base class encapsulates the functionality which the GP uses to build fragment shaders
 */
class GrGLGPFragmentBuilder : public GrGLShaderBuilder {
public:
    GrGLGPFragmentBuilder(GrGLProgramBuilder* program) : INHERITED(program) {}
    virtual ~GrGLGPFragmentBuilder() {}
    /**
     * 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.
     */
    virtual bool enableFeature(GLSLFeature) = 0;

    /**
     * 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.
     */
    virtual SkString ensureFSCoords2D(const GrGLProcessor::TransformedCoordsArray& coords,
                                      int index) = 0;


    /** 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). */
    virtual const char* fragmentPosition() = 0;

private:
    typedef GrGLShaderBuilder INHERITED;
};

/*
 * Fragment processor's, in addition to all of the above, may need to use dst color so they use
 * this builder to create their shader.  Because this is the only shader builder the FP sees, we
 * just call it FPShaderBuilder
 */
class GrGLFPFragmentBuilder : public GrGLGPFragmentBuilder {
public:
    GrGLFPFragmentBuilder(GrGLProgramBuilder* program) : INHERITED(program) {}

    /** 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. */
    virtual const char* dstColor() = 0;

private:
    typedef GrGLGPFragmentBuilder INHERITED;
};

// TODO rename to Fragment Builder
class GrGLFragmentShaderBuilder : public GrGLFPFragmentBuilder {
public:
    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&);

    GrGLFragmentShaderBuilder(GrGLProgramBuilder* program, uint8_t fragPosKey);

    // true public interface, defined explicitly in the abstract interfaces above
    virtual bool enableFeature(GLSLFeature) SK_OVERRIDE;
    virtual SkString ensureFSCoords2D(const GrGLProcessor::TransformedCoordsArray& coords,
                                      int index) SK_OVERRIDE;
    virtual const char* fragmentPosition() SK_OVERRIDE;
    virtual const char* dstColor() SK_OVERRIDE;

private:
    // Private public interface, used by GrGLProgramBuilder to build a fragment shader
    void emitCodeToReadDstTexture();
    void enableCustomOutput();
    void enableSecondaryOutput();
    const char* getPrimaryColorOutputName() const;
    const char* getSecondaryColorOutputName() const;
    void enableSecondaryOutput(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage);
    void combineColorAndCoverage(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage);
    bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
    void bindFragmentShaderLocations(GrGLuint programID);

    // As GLProcessors emit code, there are some conditions we need to verify.  We use the below
    // state to track this.  The reset call is called per processor emitted.
    bool hasReadDstColor() const { return fHasReadDstColor; }
    bool hasReadFragmentPosition() const { return fHasReadFragmentPosition; }
    void reset() {
        fHasReadDstColor = false;
        fHasReadFragmentPosition = false;
    }

    /*
     * An internal call for GrGLProgramBuilder to use to add varyings to the vertex shader
     */
    void addVarying(GrGLVarying*, GrGLShaderVar::Precision);

    /**
     * Features that should only be enabled by GrGLFragmentShaderBuilder itself.
     */
    enum GLSLPrivateFeature {
        kFragCoordConventions_GLSLPrivateFeature = kLastGLSLFeature + 1,
        kLastGLSLPrivateFeature = kFragCoordConventions_GLSLPrivateFeature
    };

    // 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.
    };

    // Interpretation of FragPosKey when generating code
    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.
    };

    static const char* kDstCopyColorName;

    bool fHasCustomColorOutput;
    bool fHasSecondaryOutput;
    bool fSetupFragPosition;
    bool fTopLeftFragPosRead;
    int  fCustomColorOutputIndex;

    // some state to verify shaders and effects are consistent, this is reset between effects by
    // the program creator
    bool fHasReadDstColor;
    bool fHasReadFragmentPosition;

    friend class GrGLNvprProgramBuilder;
    friend class GrGLProgramBuilder;

    typedef GrGLFPFragmentBuilder INHERITED;
};

#endif
