2 * Copyright 2013 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #ifndef GrGLProgramDesc_DEFINED
9 #define GrGLProgramDesc_DEFINED
11 #include "GrGLEffect.h"
12 #include "GrDrawState.h"
13 #include "GrGLShaderBuilder.h"
19 // Optionally compile the experimental GS code. Set to SK_DEBUG so that debug build bots will
21 #define GR_GL_EXPERIMENTAL_GS 1
23 #define GR_GL_EXPERIMENTAL_GS 0
27 /** This class describes a program to generate. It also serves as a program cache key. Very little
28 of this is GL-specific. There is the generation of GrGLEffect::EffectKeys and the dst-read part
29 of the key set by GrGLShaderBuilder. If the interfaces that set those portions were abstracted
30 to be API-neutral then so could this class. */
31 class GrGLProgramDesc {
33 GrGLProgramDesc() : fInitialized(false) {}
34 GrGLProgramDesc(const GrGLProgramDesc& desc) { *this = desc; }
36 // Returns this as a uint32_t array to be used as a key in the program cache.
37 const uint32_t* asKey() const {
38 SkASSERT(fInitialized);
39 return reinterpret_cast<const uint32_t*>(fKey.get());
42 // Gets the number of bytes in asKey(). It will be a 4-byte aligned value. When comparing two
43 // keys the size of either key can be used with memcmp() since the lengths themselves begin the
44 // keys and thus the memcmp will exit early if the keys are of different lengths.
45 uint32_t keyLength() const { return *this->atOffset<uint32_t, kLengthOffset>(); }
47 // Gets the a checksum of the key. Can be used as a hash value for a fast lookup in a cache.
48 uint32_t getChecksum() const { return *this->atOffset<uint32_t, kChecksumOffset>(); }
51 void setRandom(SkRandom*,
53 const GrRenderTarget* dummyDstRenderTarget,
54 const GrTexture* dummyDstCopyTexture,
55 const GrEffectStage* stages[],
57 int numCoverageStages,
61 * Builds a program descriptor from a GrDrawState. Whether the primitive type is points, the
62 * output of GrDrawState::getBlendOpts, and the caps of the GrGpuGL are also inputs. It also
63 * outputs the color and coverage stages referenced by the generated descriptor. This may
64 * not contain all stages from the draw state and coverage stages from the drawState may
65 * be treated as color stages in the output.
67 static void Build(const GrDrawState&,
68 GrGpu::DrawType drawType,
69 GrDrawState::BlendOptFlags,
70 GrBlendCoeff srcCoeff,
71 GrBlendCoeff dstCoeff,
73 const GrDeviceCoordTexture* dstCopy,
74 SkTArray<const GrEffectStage*, true>* outColorStages,
75 SkTArray<const GrEffectStage*, true>* outCoverageStages,
76 GrGLProgramDesc* outDesc);
78 int numColorEffects() const {
79 SkASSERT(fInitialized);
80 return this->getHeader().fColorEffectCnt;
83 int numCoverageEffects() const {
84 SkASSERT(fInitialized);
85 return this->getHeader().fCoverageEffectCnt;
88 int numTotalEffects() const { return this->numColorEffects() + this->numCoverageEffects(); }
90 GrGLProgramDesc& operator= (const GrGLProgramDesc& other);
92 bool operator== (const GrGLProgramDesc& other) const {
93 SkASSERT(fInitialized && other.fInitialized);
94 // The length is masked as a hint to the compiler that the address will be 4 byte aligned.
95 return 0 == memcmp(this->asKey(), other.asKey(), this->keyLength() & ~0x3);
98 bool operator!= (const GrGLProgramDesc& other) const {
99 return !(*this == other);
102 static bool Less(const GrGLProgramDesc& a, const GrGLProgramDesc& b) {
103 return memcmp(a.asKey(), b.asKey(), a.keyLength() & ~0x3) < 0;
107 // Specifies where the initial color comes from before the stages are applied.
109 kSolidWhite_ColorInput,
110 kTransBlack_ColorInput,
111 kAttribute_ColorInput,
117 enum CoverageOutput {
118 // modulate color and coverage, write result as the color output.
119 kModulate_CoverageOutput,
120 // Writes color*coverage as the primary color output and also writes coverage as the
121 // secondary output. Only set if dual source blending is supported.
122 kSecondaryCoverage_CoverageOutput,
123 // Writes color*coverage as the primary color output and also writes coverage * (1 - colorA)
124 // as the secondary output. Only set if dual source blending is supported.
125 kSecondaryCoverageISA_CoverageOutput,
126 // Writes color*coverage as the primary color output and also writes coverage *
127 // (1 - colorRGB) as the secondary output. Only set if dual source blending is supported.
128 kSecondaryCoverageISC_CoverageOutput,
129 // Combines the coverage, dst, and color as coverage * color + (1 - coverage) * dst. This
130 // can only be set if fDstReadKey is non-zero.
131 kCombineWithDst_CoverageOutput,
136 static bool CoverageOutputUsesSecondaryOutput(CoverageOutput co) {
138 case kSecondaryCoverage_CoverageOutput: // fallthru
139 case kSecondaryCoverageISA_CoverageOutput:
140 case kSecondaryCoverageISC_CoverageOutput:
148 GrGLShaderBuilder::DstReadKey fDstReadKey; // set by GrGLShaderBuilder if there
149 // are effects that must read the dst.
151 GrGLShaderBuilder::FragPosKey fFragPosKey; // set by GrGLShaderBuilder if there are
152 // effects that read the fragment position.
155 ColorInput fColorInput : 8;
156 ColorInput fCoverageInput : 8;
157 CoverageOutput fCoverageOutput : 8;
159 SkBool8 fHasVertexCode;
160 SkBool8 fEmitsPointSize;
162 // To enable experimental geometry shader code (not for use in
164 #if GR_GL_EXPERIMENTAL_GS
165 SkBool8 fExperimentalGS;
168 int8_t fPositionAttributeIndex;
169 int8_t fLocalCoordAttributeIndex;
170 int8_t fColorAttributeIndex;
171 int8_t fCoverageAttributeIndex;
173 int8_t fColorEffectCnt;
174 int8_t fCoverageEffectCnt;
177 // The key is 1 uint32_t for the length, followed another for the checksum, the header, and then
178 // the effect keys. Everything is fixed length except the effect key array.
181 kChecksumOffset = kLengthOffset + sizeof(uint32_t),
182 kHeaderOffset = kChecksumOffset + sizeof(uint32_t),
183 kHeaderSize = SkAlign4(sizeof(KeyHeader)),
184 kEffectKeyOffset = kHeaderOffset + kHeaderSize,
187 template<typename T, size_t OFFSET> T* atOffset() {
188 return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(fKey.get()) + OFFSET);
191 template<typename T, size_t OFFSET> const T* atOffset() const {
192 return reinterpret_cast<const T*>(reinterpret_cast<intptr_t>(fKey.get()) + OFFSET);
195 typedef GrGLEffect::EffectKey EffectKey;
197 uint32_t* checksum() { return this->atOffset<uint32_t, kChecksumOffset>(); }
198 KeyHeader* header() { return this->atOffset<KeyHeader, kHeaderOffset>(); }
199 EffectKey* effectKeys() { return this->atOffset<EffectKey, kEffectKeyOffset>(); }
201 const KeyHeader& getHeader() const { return *this->atOffset<KeyHeader, kHeaderOffset>(); }
202 const EffectKey* getEffectKeys() const { return this->atOffset<EffectKey, kEffectKeyOffset>(); }
204 static size_t KeyLength(int effectCnt) {
205 GR_STATIC_ASSERT(!(sizeof(EffectKey) & 0x3));
206 return kEffectKeyOffset + effectCnt * sizeof(EffectKey);
210 kMaxPreallocEffects = 16,
211 kPreAllocSize = kEffectKeyOffset + kMaxPreallocEffects * sizeof(EffectKey),
214 SkAutoSMalloc<kPreAllocSize> fKey;
217 // GrGLProgram and GrGLShaderBuilder read the private fields to generate code. TODO: Move all
218 // code generation to GrGLShaderBuilder (and maybe add getters rather than friending).
219 friend class GrGLProgram;
220 friend class GrGLShaderBuilder;
221 friend class GrGLFullShaderBuilder;
222 friend class GrGLFragmentOnlyShaderBuilder;