| 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 |