17839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger/*
27839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger * Copyright 2013 Google Inc.
37839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger *
47839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger * Use of this source code is governed by a BSD-style license that can be
57839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger * found in the LICENSE file.
67839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger */
77839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
87839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#ifndef GrGLProgramDesc_DEFINED
97839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#define GrGLProgramDesc_DEFINED
107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "GrGLEffect.h"
127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "GrDrawState.h"
137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "GrGLShaderBuilder.h"
147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerclass GrGpuGL;
167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
170a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger#ifdef SK_DEBUG
180a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger  // Optionally compile the experimental GS code. Set to SK_DEBUG so that debug build bots will
190a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger  // execute the code.
200a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger  #define GR_GL_EXPERIMENTAL_GS 1
210a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger#else
220a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger  #define GR_GL_EXPERIMENTAL_GS 0
230a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger#endif
247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger/** This class describes a program to generate. It also serves as a program cache key. Very little
277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    of this is GL-specific. There is the generation of GrGLEffect::EffectKeys and the dst-read part
287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    of the key set by GrGLShaderBuilder. If the interfaces that set those portions were abstracted
297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    to be API-neutral then so could this class. */
307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerclass GrGLProgramDesc {
317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerpublic:
32779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    GrGLProgramDesc() : fInitialized(false) {}
33779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    GrGLProgramDesc(const GrGLProgramDesc& desc) { *this = desc; }
347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
35779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    // Returns this as a uint32_t array to be used as a key in the program cache.
367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    const uint32_t* asKey() const {
370a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        SkASSERT(fInitialized);
38779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        return reinterpret_cast<const uint32_t*>(fKey.get());
397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
41779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    // Gets the number of bytes in asKey(). It will be a 4-byte aligned value. When comparing two
42779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    // keys the size of either key can be used with memcmp() since the lengths themselves begin the
43779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    // keys and thus the memcmp will exit early if the keys are of different lengths.
44779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    uint32_t keyLength() const { return *this->atOffset<uint32_t, kLengthOffset>(); }
45779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger
46779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    // Gets the a checksum of the key. Can be used as a hash value for a fast lookup in a cache.
47779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    uint32_t getChecksum() const { return *this->atOffset<uint32_t, kChecksumOffset>(); }
48779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger
497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // For unit testing.
500a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    void setRandom(SkRandom*,
517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                   const GrGpuGL* gpu,
52779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger                   const GrRenderTarget* dummyDstRenderTarget,
53779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger                   const GrTexture* dummyDstCopyTexture,
54779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger                   const GrEffectStage* stages[],
55779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger                   int numColorStages,
56779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger                   int numCoverageStages,
577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                   int currAttribIndex);
587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
597839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    /**
607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     * Builds a program descriptor from a GrDrawState. Whether the primitive type is points, the
61779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger     * output of GrDrawState::getBlendOpts, and the caps of the GrGpuGL are also inputs. It also
6258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger     * outputs the color and coverage stages referenced by the generated descriptor. This may
6358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger     * not contain all stages from the draw state and coverage stages from the drawState may
6458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger     * be treated as color stages in the output.
657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     */
667839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    static void Build(const GrDrawState&,
677839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                      bool isPoints,
687839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                      GrDrawState::BlendOptFlags,
697839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                      GrBlendCoeff srcCoeff,
707839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                      GrBlendCoeff dstCoeff,
717839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                      const GrGpuGL* gpu,
727839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                      const GrDeviceCoordTexture* dstCopy,
7358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                      SkTArray<const GrEffectStage*, true>* outColorStages,
7458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                      SkTArray<const GrEffectStage*, true>* outCoverageStages,
757839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                      GrGLProgramDesc* outDesc);
767839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
77779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    int numColorEffects() const {
780a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        SkASSERT(fInitialized);
79779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        return this->getHeader().fColorEffectCnt;
80779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    }
81779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger
82779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    int numCoverageEffects() const {
830a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        SkASSERT(fInitialized);
84779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        return this->getHeader().fCoverageEffectCnt;
85779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    }
86779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger
87779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    int numTotalEffects() const { return this->numColorEffects() + this->numCoverageEffects(); }
88779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger
89779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    GrGLProgramDesc& operator= (const GrGLProgramDesc& other);
90779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger
91779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    bool operator== (const GrGLProgramDesc& other) const {
920a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        SkASSERT(fInitialized && other.fInitialized);
93779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        // The length is masked as a hint to the compiler that the address will be 4 byte aligned.
94779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        return 0 == memcmp(this->asKey(), other.asKey(), this->keyLength() & ~0x3);
95779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    }
96779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger
97779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    bool operator!= (const GrGLProgramDesc& other) const {
98779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        return !(*this == other);
99779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    }
100779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger
101779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    static bool Less(const GrGLProgramDesc& a, const GrGLProgramDesc& b) {
102779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        return memcmp(a.asKey(), b.asKey(), a.keyLength() & ~0x3) < 0;
103779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    }
104779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger
1057839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerprivate:
1067839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // Specifies where the initial color comes from before the stages are applied.
1077839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    enum ColorInput {
1087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        kSolidWhite_ColorInput,
1097839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        kTransBlack_ColorInput,
1107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        kAttribute_ColorInput,
1117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        kUniform_ColorInput,
1127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        kColorInputCnt
1147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    };
1157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    enum CoverageOutput {
1177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        // modulate color and coverage, write result as the color output.
1187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        kModulate_CoverageOutput,
1197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        // Writes color*coverage as the primary color output and also writes coverage as the
1207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        // secondary output. Only set if dual source blending is supported.
1217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        kSecondaryCoverage_CoverageOutput,
1227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        // Writes color*coverage as the primary color output and also writes coverage * (1 - colorA)
1237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        // as the secondary output. Only set if dual source blending is supported.
1247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        kSecondaryCoverageISA_CoverageOutput,
1257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        // Writes color*coverage as the primary color output and also writes coverage *
1267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        // (1 - colorRGB) as the secondary output. Only set if dual source blending is supported.
1277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        kSecondaryCoverageISC_CoverageOutput,
1287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        // Combines the coverage, dst, and color as coverage * color + (1 - coverage) * dst. This
1297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        // can only be set if fDstReadKey is non-zero.
1307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        kCombineWithDst_CoverageOutput,
1317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        kCoverageOutputCnt
1337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    };
1347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    static bool CoverageOutputUsesSecondaryOutput(CoverageOutput co) {
1367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        switch (co) {
1377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            case kSecondaryCoverage_CoverageOutput: //  fallthru
1387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            case kSecondaryCoverageISA_CoverageOutput:
1397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            case kSecondaryCoverageISC_CoverageOutput:
1407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                return true;
1417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            default:
1427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                return false;
1437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
1447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
146779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    struct KeyHeader {
147779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        GrGLShaderBuilder::DstReadKey fDstReadKey;      // set by GrGLShaderBuilder if there
1487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                                                        // are effects that must read the dst.
1497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                                                        // Otherwise, 0.
150779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        GrGLShaderBuilder::FragPosKey fFragPosKey;      // set by GrGLShaderBuilder if there are
1517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                                                        // effects that read the fragment position.
1527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                                                        // Otherwise, 0.
1537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
154779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        // should the FS discard if the coverage is zero (to avoid stencil manipulation)
155779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        SkBool8                     fDiscardIfZeroCoverage;
1567839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1570a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        ColorInput                  fColorInput : 8;
1580a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        ColorInput                  fCoverageInput : 8;
1590a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        CoverageOutput              fCoverageOutput : 8;
1607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1610a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        SkBool8                     fHasVertexCode;
162779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        SkBool8                     fEmitsPointSize;
163779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger
164779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        // To enable experimental geometry shader code (not for use in
165779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        // production)
166779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger#if GR_GL_EXPERIMENTAL_GS
167779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        SkBool8                     fExperimentalGS;
168779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger#endif
169779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger
170779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        int8_t                      fPositionAttributeIndex;
171779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        int8_t                      fLocalCoordAttributeIndex;
172779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        int8_t                      fColorAttributeIndex;
173779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        int8_t                      fCoverageAttributeIndex;
174779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger
175779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        int8_t                      fColorEffectCnt;
176779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        int8_t                      fCoverageEffectCnt;
177779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    };
178779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger
179779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    // The key is 1 uint32_t for the length, followed another for the checksum, the header, and then
180779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    // the effect keys. Everything is fixed length except the effect key array.
181779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    enum {
182779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        kLengthOffset = 0,
183779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        kChecksumOffset = kLengthOffset + sizeof(uint32_t),
184779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        kHeaderOffset = kChecksumOffset + sizeof(uint32_t),
185779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        kHeaderSize = SkAlign4(sizeof(KeyHeader)),
186779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        kEffectKeyOffset = kHeaderOffset + kHeaderSize,
187779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    };
188779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger
189779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    template<typename T, size_t OFFSET> T* atOffset() {
190779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(fKey.get()) + OFFSET);
191779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    }
192779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger
193779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    template<typename T, size_t OFFSET> const T* atOffset() const {
194779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        return reinterpret_cast<const T*>(reinterpret_cast<intptr_t>(fKey.get()) + OFFSET);
195779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    }
196779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger
197779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    typedef GrGLEffect::EffectKey EffectKey;
198779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger
199779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    uint32_t* checksum() { return this->atOffset<uint32_t, kChecksumOffset>(); }
200779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    KeyHeader* header() { return this->atOffset<KeyHeader, kHeaderOffset>(); }
201779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    EffectKey* effectKeys() { return this->atOffset<EffectKey, kEffectKeyOffset>(); }
202779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger
203779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    const KeyHeader& getHeader() const { return *this->atOffset<KeyHeader, kHeaderOffset>(); }
204779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    const EffectKey* getEffectKeys() const { return this->atOffset<EffectKey, kEffectKeyOffset>(); }
205779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger
206779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    static size_t KeyLength(int effectCnt) {
207779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        GR_STATIC_ASSERT(!(sizeof(EffectKey) & 0x3));
208779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        return kEffectKeyOffset + effectCnt * sizeof(EffectKey);
209779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    }
210779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger
211779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    enum {
212779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        kMaxPreallocEffects = 16,
213779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger        kPreAllocSize = kEffectKeyOffset +  kMaxPreallocEffects * sizeof(EffectKey),
214779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    };
2157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
216779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    SkAutoSMalloc<kPreAllocSize> fKey;
217779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger    bool fInitialized;
2187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
2197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // GrGLProgram and GrGLShaderBuilder read the private fields to generate code. TODO: Move all
2207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // code generation to GrGLShaderBuilder (and maybe add getters rather than friending).
2217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    friend class GrGLProgram;
2227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    friend class GrGLShaderBuilder;
2230a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    friend class GrGLFullShaderBuilder;
2240a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    friend class GrGLFragmentOnlyShaderBuilder;
2257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger};
2267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
2277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#endif
228