gfx/skia/trunk/src/gpu/gl/GrGLProgramDesc.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/src/gpu/gl/GrGLProgramDesc.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,224 @@
     1.4 +/*
     1.5 + * Copyright 2013 Google Inc.
     1.6 + *
     1.7 + * Use of this source code is governed by a BSD-style license that can be
     1.8 + * found in the LICENSE file.
     1.9 + */
    1.10 +
    1.11 +#ifndef GrGLProgramDesc_DEFINED
    1.12 +#define GrGLProgramDesc_DEFINED
    1.13 +
    1.14 +#include "GrGLEffect.h"
    1.15 +#include "GrDrawState.h"
    1.16 +#include "GrGLShaderBuilder.h"
    1.17 +
    1.18 +class GrGpuGL;
    1.19 +
    1.20 +#ifdef SK_DEBUG
    1.21 +  // Optionally compile the experimental GS code. Set to SK_DEBUG so that debug build bots will
    1.22 +  // execute the code.
    1.23 +  #define GR_GL_EXPERIMENTAL_GS 1
    1.24 +#else
    1.25 +  #define GR_GL_EXPERIMENTAL_GS 0
    1.26 +#endif
    1.27 +
    1.28 +
    1.29 +/** This class describes a program to generate. It also serves as a program cache key. Very little
    1.30 +    of this is GL-specific. There is the generation of GrGLEffect::EffectKeys and the dst-read part
    1.31 +    of the key set by GrGLShaderBuilder. If the interfaces that set those portions were abstracted
    1.32 +    to be API-neutral then so could this class. */
    1.33 +class GrGLProgramDesc {
    1.34 +public:
    1.35 +    GrGLProgramDesc() : fInitialized(false) {}
    1.36 +    GrGLProgramDesc(const GrGLProgramDesc& desc) { *this = desc; }
    1.37 +
    1.38 +    // Returns this as a uint32_t array to be used as a key in the program cache.
    1.39 +    const uint32_t* asKey() const {
    1.40 +        SkASSERT(fInitialized);
    1.41 +        return reinterpret_cast<const uint32_t*>(fKey.get());
    1.42 +    }
    1.43 +
    1.44 +    // Gets the number of bytes in asKey(). It will be a 4-byte aligned value. When comparing two
    1.45 +    // keys the size of either key can be used with memcmp() since the lengths themselves begin the
    1.46 +    // keys and thus the memcmp will exit early if the keys are of different lengths.
    1.47 +    uint32_t keyLength() const { return *this->atOffset<uint32_t, kLengthOffset>(); }
    1.48 +
    1.49 +    // Gets the a checksum of the key. Can be used as a hash value for a fast lookup in a cache.
    1.50 +    uint32_t getChecksum() const { return *this->atOffset<uint32_t, kChecksumOffset>(); }
    1.51 +
    1.52 +    // For unit testing.
    1.53 +    void setRandom(SkRandom*,
    1.54 +                   const GrGpuGL* gpu,
    1.55 +                   const GrRenderTarget* dummyDstRenderTarget,
    1.56 +                   const GrTexture* dummyDstCopyTexture,
    1.57 +                   const GrEffectStage* stages[],
    1.58 +                   int numColorStages,
    1.59 +                   int numCoverageStages,
    1.60 +                   int currAttribIndex);
    1.61 +
    1.62 +    /**
    1.63 +     * Builds a program descriptor from a GrDrawState. Whether the primitive type is points, the
    1.64 +     * output of GrDrawState::getBlendOpts, and the caps of the GrGpuGL are also inputs. It also
    1.65 +     * outputs the color and coverage stages referenced by the generated descriptor. This may
    1.66 +     * not contain all stages from the draw state and coverage stages from the drawState may
    1.67 +     * be treated as color stages in the output.
    1.68 +     */
    1.69 +    static void Build(const GrDrawState&,
    1.70 +                      bool isPoints,
    1.71 +                      GrDrawState::BlendOptFlags,
    1.72 +                      GrBlendCoeff srcCoeff,
    1.73 +                      GrBlendCoeff dstCoeff,
    1.74 +                      const GrGpuGL* gpu,
    1.75 +                      const GrDeviceCoordTexture* dstCopy,
    1.76 +                      SkTArray<const GrEffectStage*, true>* outColorStages,
    1.77 +                      SkTArray<const GrEffectStage*, true>* outCoverageStages,
    1.78 +                      GrGLProgramDesc* outDesc);
    1.79 +
    1.80 +    int numColorEffects() const {
    1.81 +        SkASSERT(fInitialized);
    1.82 +        return this->getHeader().fColorEffectCnt;
    1.83 +    }
    1.84 +
    1.85 +    int numCoverageEffects() const {
    1.86 +        SkASSERT(fInitialized);
    1.87 +        return this->getHeader().fCoverageEffectCnt;
    1.88 +    }
    1.89 +
    1.90 +    int numTotalEffects() const { return this->numColorEffects() + this->numCoverageEffects(); }
    1.91 +
    1.92 +    GrGLProgramDesc& operator= (const GrGLProgramDesc& other);
    1.93 +
    1.94 +    bool operator== (const GrGLProgramDesc& other) const {
    1.95 +        SkASSERT(fInitialized && other.fInitialized);
    1.96 +        // The length is masked as a hint to the compiler that the address will be 4 byte aligned.
    1.97 +        return 0 == memcmp(this->asKey(), other.asKey(), this->keyLength() & ~0x3);
    1.98 +    }
    1.99 +
   1.100 +    bool operator!= (const GrGLProgramDesc& other) const {
   1.101 +        return !(*this == other);
   1.102 +    }
   1.103 +
   1.104 +    static bool Less(const GrGLProgramDesc& a, const GrGLProgramDesc& b) {
   1.105 +        return memcmp(a.asKey(), b.asKey(), a.keyLength() & ~0x3) < 0;
   1.106 +    }
   1.107 +
   1.108 +private:
   1.109 +    // Specifies where the initial color comes from before the stages are applied.
   1.110 +    enum ColorInput {
   1.111 +        kSolidWhite_ColorInput,
   1.112 +        kTransBlack_ColorInput,
   1.113 +        kAttribute_ColorInput,
   1.114 +        kUniform_ColorInput,
   1.115 +
   1.116 +        kColorInputCnt
   1.117 +    };
   1.118 +
   1.119 +    enum CoverageOutput {
   1.120 +        // modulate color and coverage, write result as the color output.
   1.121 +        kModulate_CoverageOutput,
   1.122 +        // Writes color*coverage as the primary color output and also writes coverage as the
   1.123 +        // secondary output. Only set if dual source blending is supported.
   1.124 +        kSecondaryCoverage_CoverageOutput,
   1.125 +        // Writes color*coverage as the primary color output and also writes coverage * (1 - colorA)
   1.126 +        // as the secondary output. Only set if dual source blending is supported.
   1.127 +        kSecondaryCoverageISA_CoverageOutput,
   1.128 +        // Writes color*coverage as the primary color output and also writes coverage *
   1.129 +        // (1 - colorRGB) as the secondary output. Only set if dual source blending is supported.
   1.130 +        kSecondaryCoverageISC_CoverageOutput,
   1.131 +        // Combines the coverage, dst, and color as coverage * color + (1 - coverage) * dst. This
   1.132 +        // can only be set if fDstReadKey is non-zero.
   1.133 +        kCombineWithDst_CoverageOutput,
   1.134 +
   1.135 +        kCoverageOutputCnt
   1.136 +    };
   1.137 +
   1.138 +    static bool CoverageOutputUsesSecondaryOutput(CoverageOutput co) {
   1.139 +        switch (co) {
   1.140 +            case kSecondaryCoverage_CoverageOutput: //  fallthru
   1.141 +            case kSecondaryCoverageISA_CoverageOutput:
   1.142 +            case kSecondaryCoverageISC_CoverageOutput:
   1.143 +                return true;
   1.144 +            default:
   1.145 +                return false;
   1.146 +        }
   1.147 +    }
   1.148 +
   1.149 +    struct KeyHeader {
   1.150 +        GrGLShaderBuilder::DstReadKey fDstReadKey;      // set by GrGLShaderBuilder if there
   1.151 +                                                        // are effects that must read the dst.
   1.152 +                                                        // Otherwise, 0.
   1.153 +        GrGLShaderBuilder::FragPosKey fFragPosKey;      // set by GrGLShaderBuilder if there are
   1.154 +                                                        // effects that read the fragment position.
   1.155 +                                                        // Otherwise, 0.
   1.156 +
   1.157 +        ColorInput                  fColorInput : 8;
   1.158 +        ColorInput                  fCoverageInput : 8;
   1.159 +        CoverageOutput              fCoverageOutput : 8;
   1.160 +
   1.161 +        SkBool8                     fHasVertexCode;
   1.162 +        SkBool8                     fEmitsPointSize;
   1.163 +
   1.164 +        // To enable experimental geometry shader code (not for use in
   1.165 +        // production)
   1.166 +#if GR_GL_EXPERIMENTAL_GS
   1.167 +        SkBool8                     fExperimentalGS;
   1.168 +#endif
   1.169 +
   1.170 +        int8_t                      fPositionAttributeIndex;
   1.171 +        int8_t                      fLocalCoordAttributeIndex;
   1.172 +        int8_t                      fColorAttributeIndex;
   1.173 +        int8_t                      fCoverageAttributeIndex;
   1.174 +
   1.175 +        int8_t                      fColorEffectCnt;
   1.176 +        int8_t                      fCoverageEffectCnt;
   1.177 +    };
   1.178 +
   1.179 +    // The key is 1 uint32_t for the length, followed another for the checksum, the header, and then
   1.180 +    // the effect keys. Everything is fixed length except the effect key array.
   1.181 +    enum {
   1.182 +        kLengthOffset = 0,
   1.183 +        kChecksumOffset = kLengthOffset + sizeof(uint32_t),
   1.184 +        kHeaderOffset = kChecksumOffset + sizeof(uint32_t),
   1.185 +        kHeaderSize = SkAlign4(sizeof(KeyHeader)),
   1.186 +        kEffectKeyOffset = kHeaderOffset + kHeaderSize,
   1.187 +    };
   1.188 +
   1.189 +    template<typename T, size_t OFFSET> T* atOffset() {
   1.190 +        return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(fKey.get()) + OFFSET);
   1.191 +    }
   1.192 +
   1.193 +    template<typename T, size_t OFFSET> const T* atOffset() const {
   1.194 +        return reinterpret_cast<const T*>(reinterpret_cast<intptr_t>(fKey.get()) + OFFSET);
   1.195 +    }
   1.196 +
   1.197 +    typedef GrGLEffect::EffectKey EffectKey;
   1.198 +
   1.199 +    uint32_t* checksum() { return this->atOffset<uint32_t, kChecksumOffset>(); }
   1.200 +    KeyHeader* header() { return this->atOffset<KeyHeader, kHeaderOffset>(); }
   1.201 +    EffectKey* effectKeys() { return this->atOffset<EffectKey, kEffectKeyOffset>(); }
   1.202 +
   1.203 +    const KeyHeader& getHeader() const { return *this->atOffset<KeyHeader, kHeaderOffset>(); }
   1.204 +    const EffectKey* getEffectKeys() const { return this->atOffset<EffectKey, kEffectKeyOffset>(); }
   1.205 +
   1.206 +    static size_t KeyLength(int effectCnt) {
   1.207 +        GR_STATIC_ASSERT(!(sizeof(EffectKey) & 0x3));
   1.208 +        return kEffectKeyOffset + effectCnt * sizeof(EffectKey);
   1.209 +    }
   1.210 +
   1.211 +    enum {
   1.212 +        kMaxPreallocEffects = 16,
   1.213 +        kPreAllocSize = kEffectKeyOffset +  kMaxPreallocEffects * sizeof(EffectKey),
   1.214 +    };
   1.215 +
   1.216 +    SkAutoSMalloc<kPreAllocSize> fKey;
   1.217 +    bool fInitialized;
   1.218 +
   1.219 +    // GrGLProgram and GrGLShaderBuilder read the private fields to generate code. TODO: Move all
   1.220 +    // code generation to GrGLShaderBuilder (and maybe add getters rather than friending).
   1.221 +    friend class GrGLProgram;
   1.222 +    friend class GrGLShaderBuilder;
   1.223 +    friend class GrGLFullShaderBuilder;
   1.224 +    friend class GrGLFragmentOnlyShaderBuilder;
   1.225 +};
   1.226 +
   1.227 +#endif

mercurial