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

#ifndef GrGLProgramDesc_DEFINED
#define GrGLProgramDesc_DEFINED

#include "GrGLEffect.h"
#include "GrDrawState.h"
#include "GrGpu.h"

class GrGpuGL;

#ifdef SK_DEBUG
  // Optionally compile the experimental GS code. Set to SK_DEBUG so that debug build bots will
  // execute the code.
  #define GR_GL_EXPERIMENTAL_GS 1
#else
  #define GR_GL_EXPERIMENTAL_GS 0
#endif


/** This class describes a program to generate. It also serves as a program cache key. Very little
    of this is GL-specific. The GL-specific parts could be factored out into a subclass. */
class GrGLProgramDesc {
public:
    GrGLProgramDesc() {}
    GrGLProgramDesc(const GrGLProgramDesc& desc) { *this = desc; }

    // Returns this as a uint32_t array to be used as a key in the program cache.
    const uint32_t* asKey() const {
        return reinterpret_cast<const uint32_t*>(fKey.begin());
    }

    // Gets the number of bytes in asKey(). It will be a 4-byte aligned value. When comparing two
    // keys the size of either key can be used with memcmp() since the lengths themselves begin the
    // keys and thus the memcmp will exit early if the keys are of different lengths.
    uint32_t keyLength() const { return *this->atOffset<uint32_t, kLengthOffset>(); }

    // Gets the a checksum of the key. Can be used as a hash value for a fast lookup in a cache.
    uint32_t getChecksum() const { return *this->atOffset<uint32_t, kChecksumOffset>(); }

    // For unit testing.
    bool setRandom(SkRandom*,
                   const GrGpuGL* gpu,
                   const GrRenderTarget* dummyDstRenderTarget,
                   const GrTexture* dummyDstCopyTexture,
                   const GrEffectStage* stages[],
                   int numColorStages,
                   int numCoverageStages,
                   int currAttribIndex);

    /**
     * Builds a program descriptor from a GrDrawState. Whether the primitive type is points, the
     * output of GrDrawState::getBlendOpts, and the caps of the GrGpuGL are also inputs. It also
     * outputs the color and coverage stages referenced by the generated descriptor. This may
     * not contain all stages from the draw state and coverage stages from the drawState may
     * be treated as color stages in the output.
     */
    static bool Build(const GrDrawState&,
                      GrGpu::DrawType drawType,
                      GrDrawState::BlendOptFlags,
                      GrBlendCoeff srcCoeff,
                      GrBlendCoeff dstCoeff,
                      const GrGpuGL* gpu,
                      const GrDeviceCoordTexture* dstCopy,
                      SkTArray<const GrEffectStage*, true>* outColorStages,
                      SkTArray<const GrEffectStage*, true>* outCoverageStages,
                      GrGLProgramDesc* outDesc);

    int numColorEffects() const {
        return this->getHeader().fColorEffectCnt;
    }

    int numCoverageEffects() const {
        return this->getHeader().fCoverageEffectCnt;
    }

    int numTotalEffects() const { return this->numColorEffects() + this->numCoverageEffects(); }

    GrGLProgramDesc& operator= (const GrGLProgramDesc& other);

    bool operator== (const GrGLProgramDesc& other) const {
        // The length is masked as a hint to the compiler that the address will be 4 byte aligned.
        return 0 == memcmp(this->asKey(), other.asKey(), this->keyLength() & ~0x3);
    }

    bool operator!= (const GrGLProgramDesc& other) const {
        return !(*this == other);
    }

    static bool Less(const GrGLProgramDesc& a, const GrGLProgramDesc& b) {
        return memcmp(a.asKey(), b.asKey(), a.keyLength() & ~0x3) < 0;
    }

private:
    // Specifies where the initial color comes from before the stages are applied.
    enum ColorInput {
        kAllOnes_ColorInput,
        kAttribute_ColorInput,
        kUniform_ColorInput,

        kColorInputCnt
    };

    enum CoverageOutput {
        // modulate color and coverage, write result as the color output.
        kModulate_CoverageOutput,
        // Writes color*coverage as the primary color output and also writes coverage as the
        // secondary output. Only set if dual source blending is supported.
        kSecondaryCoverage_CoverageOutput,
        // Writes color*coverage as the primary color output and also writes coverage * (1 - colorA)
        // as the secondary output. Only set if dual source blending is supported.
        kSecondaryCoverageISA_CoverageOutput,
        // Writes color*coverage as the primary color output and also writes coverage *
        // (1 - colorRGB) as the secondary output. Only set if dual source blending is supported.
        kSecondaryCoverageISC_CoverageOutput,
        // Combines the coverage, dst, and color as coverage * color + (1 - coverage) * dst. This
        // can only be set if fDstReadKey is non-zero.
        kCombineWithDst_CoverageOutput,

        kCoverageOutputCnt
    };

    static bool CoverageOutputUsesSecondaryOutput(CoverageOutput co) {
        switch (co) {
            case kSecondaryCoverage_CoverageOutput: //  fallthru
            case kSecondaryCoverageISA_CoverageOutput:
            case kSecondaryCoverageISC_CoverageOutput:
                return true;
            default:
                return false;
        }
    }

    struct KeyHeader {
        uint8_t                     fDstReadKey;        // set by GrGLShaderBuilder if there
                                                        // are effects that must read the dst.
                                                        // Otherwise, 0.
        uint8_t                     fFragPosKey;        // set by GrGLShaderBuilder if there are
                                                        // effects that read the fragment position.
                                                        // Otherwise, 0.
        ColorInput                  fColorInput : 8;
        ColorInput                  fCoverageInput : 8;
        CoverageOutput              fCoverageOutput : 8;

        SkBool8                     fRequiresVertexShader;
        SkBool8                     fEmitsPointSize;

        // To enable experimental geometry shader code (not for use in
        // production)
#if GR_GL_EXPERIMENTAL_GS
        SkBool8                     fExperimentalGS;
#endif

        int8_t                      fPositionAttributeIndex;
        int8_t                      fLocalCoordAttributeIndex;
        int8_t                      fColorAttributeIndex;
        int8_t                      fCoverageAttributeIndex;

        int8_t                      fColorEffectCnt;
        int8_t                      fCoverageEffectCnt;
    };

    // The key, stored in fKey, is composed of five parts:
    // 1. uint32_t for total key length.
    // 2. uint32_t for a checksum.
    // 3. Header struct defined above.
    // 4. An array of offsets to effect keys and their sizes (see 5). uint16_t for each
    //    offset and size.
    // 5. per-effect keys. Each effect's key is a variable length array of uint32_t.
    enum {
        // Part 1.
        kLengthOffset = 0,
        // Part 2.
        kChecksumOffset = kLengthOffset + sizeof(uint32_t),
        // Part 3.
        kHeaderOffset = kChecksumOffset + sizeof(uint32_t),
        kHeaderSize = SkAlign4(sizeof(KeyHeader)),
        // Part 4.
        // This is the offset in the overall key to the array of per-effect offset,length pairs.
        kEffectKeyOffsetsAndLengthOffset = kHeaderOffset + kHeaderSize,
    };

    template<typename T, size_t OFFSET> T* atOffset() {
        return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(fKey.begin()) + OFFSET);
    }

    template<typename T, size_t OFFSET> const T* atOffset() const {
        return reinterpret_cast<const T*>(reinterpret_cast<intptr_t>(fKey.begin()) + OFFSET);
    }

    KeyHeader* header() { return this->atOffset<KeyHeader, kHeaderOffset>(); }

    // Shared code between setRandom() and Build().
    static bool GetEffectKeyAndUpdateStats(const GrEffectStage& stage,
                                           const GrGLCaps& caps,
                                           bool useExplicitLocalCoords,
                                           GrEffectKeyBuilder* b,
                                           uint16_t* effectKeySize,
                                           bool* setTrueIfReadsDst,
                                           bool* setTrueIfReadsPos,
                                           bool* setTrueIfRequiresVertexShader);

    void finalize();

    const KeyHeader& getHeader() const { return *this->atOffset<KeyHeader, kHeaderOffset>(); }

    /** Used to provide effects' keys to their emitCode() function. */
    class EffectKeyProvider {
    public:
        enum EffectType {
            kColor_EffectType,
            kCoverage_EffectType,
        };

        EffectKeyProvider(const GrGLProgramDesc* desc, EffectType type) : fDesc(desc) {
            // Coverage effect key offsets begin immediately after those of the color effects.
            fBaseIndex = kColor_EffectType == type ? 0 : desc->numColorEffects();
        }

        GrEffectKey get(int index) const {
            const uint16_t* offsetsAndLengths = reinterpret_cast<const uint16_t*>(
                fDesc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset);
            // We store two uint16_ts per effect, one for the offset to the effect's key and one for
            // its length. Here we just need the offset.
            uint16_t offset = offsetsAndLengths[2 * (fBaseIndex + index) + 0];
            uint16_t length = offsetsAndLengths[2 * (fBaseIndex + index) + 1];
            // Currently effects must add to the key in units of uint32_t.
            SkASSERT(0 == (length % sizeof(uint32_t)));
            return GrEffectKey(reinterpret_cast<const uint32_t*>(fDesc->fKey.begin() + offset),
                               length / sizeof(uint32_t));
        }
    private:
        const GrGLProgramDesc*  fDesc;
        int                     fBaseIndex;
    };

    enum {
        kMaxPreallocEffects = 8,
        kIntsPerEffect      = 4,    // This is an overestimate of the average effect key size.
        kPreAllocSize = kEffectKeyOffsetsAndLengthOffset +
                        kMaxPreallocEffects * sizeof(uint32_t) * kIntsPerEffect,
    };

    SkSTArray<kPreAllocSize, uint8_t, true> fKey;

    // GrGLProgram and GrGLShaderBuilder read the private fields to generate code. TODO: Split out
    // part of GrGLShaderBuilder that is used by effects so that this header doesn't need to be
    // visible to GrGLEffects. Then make public accessors as necessary and remove friends.
    friend class GrGLProgram;
    friend class GrGLProgramBuilder;
    friend class GrGLFullProgramBuilder;
    friend class GrGLFragmentOnlyProgramBuilder;
    friend class GrGLVertexShaderBuilder;
    friend class GrGLFragmentShaderBuilder;
    friend class GrGLGeometryShaderBuilder;
};

#endif
