OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #ifndef GrGLProgramDesc_DEFINED | 8 #ifndef GrGLProgramDesc_DEFINED |
9 #define GrGLProgramDesc_DEFINED | 9 #define GrGLProgramDesc_DEFINED |
10 | 10 |
11 #include "GrGLEffect.h" | 11 #include "GrGLEffect.h" |
12 #include "GrDrawState.h" | 12 #include "GrDrawState.h" |
13 #include "GrGLShaderBuilder.h" | |
14 #include "GrGpu.h" | 13 #include "GrGpu.h" |
15 | 14 |
16 class GrGpuGL; | 15 class GrGpuGL; |
17 | 16 |
18 #ifdef SK_DEBUG | 17 #ifdef SK_DEBUG |
19 // Optionally compile the experimental GS code. Set to SK_DEBUG so that debug
build bots will | 18 // Optionally compile the experimental GS code. Set to SK_DEBUG so that debug
build bots will |
20 // execute the code. | 19 // execute the code. |
21 #define GR_GL_EXPERIMENTAL_GS 1 | 20 #define GR_GL_EXPERIMENTAL_GS 1 |
22 #else | 21 #else |
23 #define GR_GL_EXPERIMENTAL_GS 0 | 22 #define GR_GL_EXPERIMENTAL_GS 0 |
24 #endif | 23 #endif |
25 | 24 |
26 | 25 |
27 /** This class describes a program to generate. It also serves as a program cach
e key. Very little | 26 /** This class describes a program to generate. It also serves as a program cach
e key. Very little |
28 of this is GL-specific. There is the generation of GrGLEffect::EffectKeys an
d the dst-read part | 27 of this is GL-specific. There is the generation of GrGLEffect::EffectKeys an
d the dst-read part |
29 of the key set by GrGLShaderBuilder. If the interfaces that set those portio
ns were abstracted | 28 of the key set by GrGLShaderBuilder. If the interfaces that set those portio
ns were abstracted |
30 to be API-neutral then so could this class. */ | 29 to be API-neutral then so could this class. */ |
31 class GrGLProgramDesc { | 30 class GrGLProgramDesc { |
32 public: | 31 public: |
33 GrGLProgramDesc() : fInitialized(false) {} | 32 GrGLProgramDesc() {} |
34 GrGLProgramDesc(const GrGLProgramDesc& desc) { *this = desc; } | 33 GrGLProgramDesc(const GrGLProgramDesc& desc) { *this = desc; } |
35 | 34 |
36 // Returns this as a uint32_t array to be used as a key in the program cache
. | 35 // Returns this as a uint32_t array to be used as a key in the program cache
. |
37 const uint32_t* asKey() const { | 36 const uint32_t* asKey() const { |
38 SkASSERT(fInitialized); | 37 return reinterpret_cast<const uint32_t*>(fKey.begin()); |
39 return reinterpret_cast<const uint32_t*>(fKey.get()); | |
40 } | 38 } |
41 | 39 |
42 // Gets the number of bytes in asKey(). It will be a 4-byte aligned value. W
hen comparing two | 40 // Gets the number of bytes in asKey(). It will be a 4-byte aligned value. W
hen comparing two |
43 // keys the size of either key can be used with memcmp() since the lengths t
hemselves begin the | 41 // keys the size of either key can be used with memcmp() since the lengths t
hemselves begin the |
44 // keys and thus the memcmp will exit early if the keys are of different len
gths. | 42 // keys and thus the memcmp will exit early if the keys are of different len
gths. |
45 uint32_t keyLength() const { return *this->atOffset<uint32_t, kLengthOffset>
(); } | 43 uint32_t keyLength() const { return *this->atOffset<uint32_t, kLengthOffset>
(); } |
46 | 44 |
47 // Gets the a checksum of the key. Can be used as a hash value for a fast lo
okup in a cache. | 45 // Gets the a checksum of the key. Can be used as a hash value for a fast lo
okup in a cache. |
48 uint32_t getChecksum() const { return *this->atOffset<uint32_t, kChecksumOff
set>(); } | 46 uint32_t getChecksum() const { return *this->atOffset<uint32_t, kChecksumOff
set>(); } |
49 | 47 |
50 // For unit testing. | 48 // For unit testing. |
51 void setRandom(SkRandom*, | 49 bool setRandom(SkRandom*, |
52 const GrGpuGL* gpu, | 50 const GrGpuGL* gpu, |
53 const GrRenderTarget* dummyDstRenderTarget, | 51 const GrRenderTarget* dummyDstRenderTarget, |
54 const GrTexture* dummyDstCopyTexture, | 52 const GrTexture* dummyDstCopyTexture, |
55 const GrEffectStage* stages[], | 53 const GrEffectStage* stages[], |
56 int numColorStages, | 54 int numColorStages, |
57 int numCoverageStages, | 55 int numCoverageStages, |
58 int currAttribIndex); | 56 int currAttribIndex); |
59 | 57 |
60 /** | 58 /** |
61 * Builds a program descriptor from a GrDrawState. Whether the primitive typ
e is points, the | 59 * Builds a program descriptor from a GrDrawState. Whether the primitive typ
e is points, the |
62 * output of GrDrawState::getBlendOpts, and the caps of the GrGpuGL are also
inputs. It also | 60 * 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 descrip
tor. This may | 61 * outputs the color and coverage stages referenced by the generated descrip
tor. This may |
64 * not contain all stages from the draw state and coverage stages from the d
rawState may | 62 * not contain all stages from the draw state and coverage stages from the d
rawState may |
65 * be treated as color stages in the output. | 63 * be treated as color stages in the output. |
66 */ | 64 */ |
67 static void Build(const GrDrawState&, | 65 static bool Build(const GrDrawState&, |
68 GrGpu::DrawType drawType, | 66 GrGpu::DrawType drawType, |
69 GrDrawState::BlendOptFlags, | 67 GrDrawState::BlendOptFlags, |
70 GrBlendCoeff srcCoeff, | 68 GrBlendCoeff srcCoeff, |
71 GrBlendCoeff dstCoeff, | 69 GrBlendCoeff dstCoeff, |
72 const GrGpuGL* gpu, | 70 const GrGpuGL* gpu, |
73 const GrDeviceCoordTexture* dstCopy, | 71 const GrDeviceCoordTexture* dstCopy, |
74 SkTArray<const GrEffectStage*, true>* outColorStages, | 72 SkTArray<const GrEffectStage*, true>* outColorStages, |
75 SkTArray<const GrEffectStage*, true>* outCoverageStages, | 73 SkTArray<const GrEffectStage*, true>* outCoverageStages, |
76 GrGLProgramDesc* outDesc); | 74 GrGLProgramDesc* outDesc); |
77 | 75 |
78 int numColorEffects() const { | 76 int numColorEffects() const { |
79 SkASSERT(fInitialized); | |
80 return this->getHeader().fColorEffectCnt; | 77 return this->getHeader().fColorEffectCnt; |
81 } | 78 } |
82 | 79 |
83 int numCoverageEffects() const { | 80 int numCoverageEffects() const { |
84 SkASSERT(fInitialized); | |
85 return this->getHeader().fCoverageEffectCnt; | 81 return this->getHeader().fCoverageEffectCnt; |
86 } | 82 } |
87 | 83 |
88 int numTotalEffects() const { return this->numColorEffects() + this->numCove
rageEffects(); } | 84 int numTotalEffects() const { return this->numColorEffects() + this->numCove
rageEffects(); } |
89 | 85 |
90 GrGLProgramDesc& operator= (const GrGLProgramDesc& other); | 86 GrGLProgramDesc& operator= (const GrGLProgramDesc& other); |
91 | 87 |
92 bool operator== (const GrGLProgramDesc& other) const { | 88 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. | 89 // 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() & ~0x
3); | 90 return 0 == memcmp(this->asKey(), other.asKey(), this->keyLength() & ~0x
3); |
96 } | 91 } |
97 | 92 |
98 bool operator!= (const GrGLProgramDesc& other) const { | 93 bool operator!= (const GrGLProgramDesc& other) const { |
99 return !(*this == other); | 94 return !(*this == other); |
100 } | 95 } |
101 | 96 |
102 static bool Less(const GrGLProgramDesc& a, const GrGLProgramDesc& b) { | 97 static bool Less(const GrGLProgramDesc& a, const GrGLProgramDesc& b) { |
103 return memcmp(a.asKey(), b.asKey(), a.keyLength() & ~0x3) < 0; | 98 return memcmp(a.asKey(), b.asKey(), a.keyLength() & ~0x3) < 0; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 case kSecondaryCoverage_CoverageOutput: // fallthru | 133 case kSecondaryCoverage_CoverageOutput: // fallthru |
139 case kSecondaryCoverageISA_CoverageOutput: | 134 case kSecondaryCoverageISA_CoverageOutput: |
140 case kSecondaryCoverageISC_CoverageOutput: | 135 case kSecondaryCoverageISC_CoverageOutput: |
141 return true; | 136 return true; |
142 default: | 137 default: |
143 return false; | 138 return false; |
144 } | 139 } |
145 } | 140 } |
146 | 141 |
147 struct KeyHeader { | 142 struct KeyHeader { |
148 GrGLShaderBuilder::DstReadKey fDstReadKey; // set by GrGLShaderBuil
der if there | 143 uint8_t fDstReadKey; // set by GrGLShaderBuil
der if there |
149 // are effects that must
read the dst. | 144 // are effects that must
read the dst. |
150 // Otherwise, 0. | 145 // Otherwise, 0. |
151 GrGLShaderBuilder::FragPosKey fFragPosKey; // set by GrGLShaderBuil
der if there are | 146 uint8_t fFragPosKey; // set by GrGLShaderBuil
der if there are |
152 // effects that read the
fragment position. | 147 // effects that read the
fragment position. |
153 // Otherwise, 0. | 148 // Otherwise, 0. |
154 | |
155 ColorInput fColorInput : 8; | 149 ColorInput fColorInput : 8; |
156 ColorInput fCoverageInput : 8; | 150 ColorInput fCoverageInput : 8; |
157 CoverageOutput fCoverageOutput : 8; | 151 CoverageOutput fCoverageOutput : 8; |
158 | 152 |
159 SkBool8 fHasVertexCode; | 153 SkBool8 fHasVertexCode; |
160 SkBool8 fEmitsPointSize; | 154 SkBool8 fEmitsPointSize; |
161 | 155 |
162 // To enable experimental geometry shader code (not for use in | 156 // To enable experimental geometry shader code (not for use in |
163 // production) | 157 // production) |
164 #if GR_GL_EXPERIMENTAL_GS | 158 #if GR_GL_EXPERIMENTAL_GS |
165 SkBool8 fExperimentalGS; | 159 SkBool8 fExperimentalGS; |
166 #endif | 160 #endif |
167 | 161 |
168 int8_t fPositionAttributeIndex; | 162 int8_t fPositionAttributeIndex; |
169 int8_t fLocalCoordAttributeIndex; | 163 int8_t fLocalCoordAttributeIndex; |
170 int8_t fColorAttributeIndex; | 164 int8_t fColorAttributeIndex; |
171 int8_t fCoverageAttributeIndex; | 165 int8_t fCoverageAttributeIndex; |
172 | 166 |
173 int8_t fColorEffectCnt; | 167 int8_t fColorEffectCnt; |
174 int8_t fCoverageEffectCnt; | 168 int8_t fCoverageEffectCnt; |
175 }; | 169 }; |
176 | 170 |
177 // The key is 1 uint32_t for the length, followed another for the checksum,
the header, and then | 171 // The key, stored in fKey, is composed of five parts: |
178 // the effect keys. Everything is fixed length except the effect key array. | 172 // 1. uint32_t for total key length. |
| 173 // 2. uint32_t for a checksum. |
| 174 // 3. Header struct defined above. |
| 175 // 4. uint32_t offsets to beginning of every effects' key (see 5). |
| 176 // 5. per-effect keys. Each effect's key is a variable length array of uint3
2_t. |
179 enum { | 177 enum { |
180 kLengthOffset = 0, | 178 kLengthOffset = 0, |
181 kChecksumOffset = kLengthOffset + sizeof(uint32_t), | 179 kChecksumOffset = kLengthOffset + sizeof(uint32_t), |
182 kHeaderOffset = kChecksumOffset + sizeof(uint32_t), | 180 kHeaderOffset = kChecksumOffset + sizeof(uint32_t), |
183 kHeaderSize = SkAlign4(sizeof(KeyHeader)), | 181 kHeaderSize = SkAlign4(sizeof(KeyHeader)), |
184 kEffectKeyOffset = kHeaderOffset + kHeaderSize, | 182 kEffectKeyLengthsOffset = kHeaderOffset + kHeaderSize, |
185 }; | 183 }; |
186 | 184 |
187 template<typename T, size_t OFFSET> T* atOffset() { | 185 template<typename T, size_t OFFSET> T* atOffset() { |
188 return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(fKey.get()) + OFF
SET); | 186 return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(fKey.begin()) + O
FFSET); |
189 } | 187 } |
190 | 188 |
191 template<typename T, size_t OFFSET> const T* atOffset() const { | 189 template<typename T, size_t OFFSET> const T* atOffset() const { |
192 return reinterpret_cast<const T*>(reinterpret_cast<intptr_t>(fKey.get())
+ OFFSET); | 190 return reinterpret_cast<const T*>(reinterpret_cast<intptr_t>(fKey.begin(
)) + OFFSET); |
193 } | 191 } |
194 | 192 |
195 typedef GrGLEffect::EffectKey EffectKey; | 193 typedef GrBackendEffectFactory::EffectKey EffectKey; |
196 | 194 |
197 uint32_t* checksum() { return this->atOffset<uint32_t, kChecksumOffset>(); } | |
198 KeyHeader* header() { return this->atOffset<KeyHeader, kHeaderOffset>(); } | 195 KeyHeader* header() { return this->atOffset<KeyHeader, kHeaderOffset>(); } |
199 EffectKey* effectKeys() { return this->atOffset<EffectKey, kEffectKeyOffset>
(); } | 196 |
| 197 void finalize(); |
200 | 198 |
201 const KeyHeader& getHeader() const { return *this->atOffset<KeyHeader, kHead
erOffset>(); } | 199 const KeyHeader& getHeader() const { return *this->atOffset<KeyHeader, kHead
erOffset>(); } |
202 const EffectKey* getEffectKeys() const { return this->atOffset<EffectKey, kE
ffectKeyOffset>(); } | |
203 | 200 |
204 static size_t KeyLength(int effectCnt) { | 201 /** Used to provide effects' keys to their emitCode() function. */ |
205 GR_STATIC_ASSERT(!(sizeof(EffectKey) & 0x3)); | 202 class EffectKeyProvider { |
206 return kEffectKeyOffset + effectCnt * sizeof(EffectKey); | 203 public: |
207 } | 204 enum EffectType { |
| 205 kColor_EffectType, |
| 206 kCoverage_EffectType, |
| 207 }; |
| 208 |
| 209 EffectKeyProvider(const GrGLProgramDesc* desc, EffectType type) : fDesc(
desc) { |
| 210 // Coverage effect key offsets begin immediately after those of the
color effects. |
| 211 fBaseIndex = kColor_EffectType == type ? 0 : desc->numColorEffects()
; |
| 212 } |
| 213 |
| 214 EffectKey get(int index) const { |
| 215 const uint32_t* offsets = reinterpret_cast<const uint32_t*>(fDesc->f
Key.begin() + |
| 216 kEffectK
eyLengthsOffset); |
| 217 uint32_t offset = offsets[fBaseIndex + index]; |
| 218 return *reinterpret_cast<const EffectKey*>(fDesc->fKey.begin() + off
set); |
| 219 } |
| 220 private: |
| 221 const GrGLProgramDesc* fDesc; |
| 222 int fBaseIndex; |
| 223 }; |
208 | 224 |
209 enum { | 225 enum { |
210 kMaxPreallocEffects = 16, | 226 kMaxPreallocEffects = 8, |
211 kPreAllocSize = kEffectKeyOffset + kMaxPreallocEffects * sizeof(EffectK
ey), | 227 kIntsPerEffect = 4, // This is an overestimate of the average ef
fect key size. |
| 228 kPreAllocSize = kEffectKeyLengthsOffset + |
| 229 kMaxPreallocEffects * sizeof(uint32_t) * kIntsPerEffect, |
212 }; | 230 }; |
213 | 231 |
214 SkAutoSMalloc<kPreAllocSize> fKey; | 232 SkSTArray<kPreAllocSize, uint8_t, true> fKey; |
215 bool fInitialized; | |
216 | 233 |
217 // GrGLProgram and GrGLShaderBuilder read the private fields to generate cod
e. TODO: Move all | 234 // GrGLProgram and GrGLShaderBuilder read the private fields to generate cod
e. TODO: Split out |
218 // code generation to GrGLShaderBuilder (and maybe add getters rather than f
riending). | 235 // part of GrGLShaderBuilder that is used by effects so that this header doe
sn't need to be |
| 236 // visible to GrGLEffects. Then make public accessors as necessary and remov
e friends. |
219 friend class GrGLProgram; | 237 friend class GrGLProgram; |
220 friend class GrGLShaderBuilder; | 238 friend class GrGLShaderBuilder; |
221 friend class GrGLFullShaderBuilder; | 239 friend class GrGLFullShaderBuilder; |
222 friend class GrGLFragmentOnlyShaderBuilder; | 240 friend class GrGLFragmentOnlyShaderBuilder; |
223 }; | 241 }; |
224 | 242 |
225 #endif | 243 #endif |
OLD | NEW |