Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2013 Google Inc. | 2 * Copyright 2014 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 GrProgramDesc_DEFINED |
| 9 #define GrGLProgramDesc_DEFINED | 9 #define GrProgramDesc_DEFINED |
| 10 | 10 |
| 11 #include "GrGLProcessor.h" | 11 #include "GrColor.h" |
| 12 #include "GrDrawState.h" | |
| 13 #include "GrGpu.h" | 12 #include "GrGpu.h" |
| 14 #include "GrOptDrawState.h" | 13 #include "GrTypesPriv.h" |
| 15 | 14 |
| 16 class GrGpuGL; | 15 class GrGpuGL; |
| 17 | 16 |
| 18 /** This class describes a program to generate. It also serves as a program cach e key. Very little | 17 /** This class describes a program to generate. It also serves as a program cach e key. Very little |
| 19 of this is GL-specific. The GL-specific parts could be factored out into a s ubclass. */ | 18 of this is GL-specific. The GL-specific parts could be factored out into a s ubclass. */ |
| 20 class GrGLProgramDesc { | 19 class GrProgramDesc { |
| 21 public: | 20 public: |
| 22 GrGLProgramDesc() {} | 21 // Dummy constructor creates a zombie descriptor |
|
bsalomon
2014/10/23 18:10:30
This seems like an unhelpful comment. Can you eith
| |
| 23 GrGLProgramDesc(const GrGLProgramDesc& desc) { *this = desc; } | 22 GrProgramDesc() {} |
| 24 | 23 |
| 25 // Returns this as a uint32_t array to be used as a key in the program cache . | 24 // Returns this as a uint32_t array to be used as a key in the program cache . |
| 26 const uint32_t* asKey() const { | 25 const uint32_t* asKey() const { |
| 27 return reinterpret_cast<const uint32_t*>(fKey.begin()); | 26 return reinterpret_cast<const uint32_t*>(fKey.begin()); |
| 28 } | 27 } |
| 29 | 28 |
| 30 // Gets the number of bytes in asKey(). It will be a 4-byte aligned value. W hen comparing two | 29 // Gets the number of bytes in asKey(). It will be a 4-byte aligned value. W hen comparing two |
| 31 // keys the size of either key can be used with memcmp() since the lengths t hemselves begin the | 30 // keys the size of either key can be used with memcmp() since the lengths t hemselves begin the |
| 32 // keys and thus the memcmp will exit early if the keys are of different len gths. | 31 // keys and thus the memcmp will exit early if the keys are of different len gths. |
| 33 uint32_t keyLength() const { return *this->atOffset<uint32_t, kLengthOffset> (); } | 32 uint32_t keyLength() const { return *this->atOffset<uint32_t, kLengthOffset> (); } |
| 34 | 33 |
| 35 // Gets the a checksum of the key. Can be used as a hash value for a fast lo okup in a cache. | 34 // Gets the a checksum of the key. Can be used as a hash value for a fast lo okup in a cache. |
| 36 uint32_t getChecksum() const { return *this->atOffset<uint32_t, kChecksumOff set>(); } | 35 uint32_t getChecksum() const { return *this->atOffset<uint32_t, kChecksumOff set>(); } |
| 37 | 36 |
| 38 /** | 37 GrProgramDesc& operator= (const GrProgramDesc& other) { |
| 39 * Builds a program descriptor from a GrOptDrawState. Whether the primitive type is points, and | 38 size_t keyLength = other.keyLength(); |
| 40 * the caps of the GrGpuGL are also inputs. It also outputs the color and co verage stages | 39 fKey.reset(keyLength); |
| 41 * referenced by the generated descriptor. Coverage stages from the drawStat e may be treated as | 40 memcpy(fKey.begin(), other.fKey.begin(), keyLength); |
| 42 * color stages in the output. | 41 return *this; |
| 43 */ | |
| 44 static bool Build(const GrOptDrawState&, | |
| 45 GrGpu::DrawType, | |
| 46 GrGpuGL*, | |
| 47 const GrDeviceCoordTexture*, | |
| 48 GrGLProgramDesc*); | |
| 49 | |
| 50 bool hasGeometryProcessor() const { | |
| 51 return SkToBool(this->getHeader().fHasGeometryProcessor); | |
| 52 } | 42 } |
| 53 | 43 |
| 54 int numColorEffects() const { | 44 bool operator== (const GrProgramDesc& other) const { |
| 55 return this->getHeader().fColorEffectCnt; | |
| 56 } | |
| 57 | |
| 58 int numCoverageEffects() const { | |
| 59 return this->getHeader().fCoverageEffectCnt; | |
| 60 } | |
| 61 | |
| 62 int numTotalEffects() const { return this->numColorEffects() + this->numCove rageEffects(); } | |
| 63 | |
| 64 GrGLProgramDesc& operator= (const GrGLProgramDesc& other); | |
| 65 | |
| 66 bool operator== (const GrGLProgramDesc& other) const { | |
| 67 // The length is masked as a hint to the compiler that the address will be 4 byte aligned. | 45 // The length is masked as a hint to the compiler that the address will be 4 byte aligned. |
| 68 return 0 == memcmp(this->asKey(), other.asKey(), this->keyLength() & ~0x 3); | 46 return 0 == memcmp(this->asKey(), other.asKey(), this->keyLength() & ~0x 3); |
| 69 } | 47 } |
| 70 | 48 |
| 71 bool operator!= (const GrGLProgramDesc& other) const { | 49 bool operator!= (const GrProgramDesc& other) const { |
| 72 return !(*this == other); | 50 return !(*this == other); |
| 73 } | 51 } |
| 74 | 52 |
| 75 static bool Less(const GrGLProgramDesc& a, const GrGLProgramDesc& b) { | 53 static bool Less(const GrProgramDesc& a, const GrProgramDesc& b) { |
| 76 return memcmp(a.asKey(), b.asKey(), a.keyLength() & ~0x3) < 0; | 54 return memcmp(a.asKey(), b.asKey(), a.keyLength() & ~0x3) < 0; |
| 77 } | 55 } |
| 78 | 56 |
| 79 private: | 57 |
| 58 /////////////////////////////////////////////////////////////////////////// | |
| 59 /// @name Stage Output Types | |
| 60 //// | |
| 61 | |
| 62 enum PrimaryOutputType { | |
| 63 // Modulate color and coverage, write result as the color output. | |
| 64 kModulate_PrimaryOutputType, | |
| 65 // Combines the coverage, dst, and color as coverage * color + (1 - cove rage) * dst. This | |
| 66 // can only be set if fDstReadKey is non-zero. | |
| 67 kCombineWithDst_PrimaryOutputType, | |
| 68 | |
| 69 kPrimaryOutputTypeCnt, | |
| 70 }; | |
| 71 | |
| 72 enum SecondaryOutputType { | |
| 73 // There is no secondary output | |
| 74 kNone_SecondaryOutputType, | |
| 75 // Writes coverage as the secondary output. Only set if dual source blen ding is supported | |
| 76 // and primary output is kModulate. | |
| 77 kCoverage_SecondaryOutputType, | |
| 78 // Writes coverage * (1 - colorA) as the secondary output. Only set if d ual source blending | |
| 79 // is supported and primary output is kModulate. | |
| 80 kCoverageISA_SecondaryOutputType, | |
| 81 // Writes coverage * (1 - colorRGBA) as the secondary output. Only set i f dual source | |
| 82 // blending is supported and primary output is kModulate. | |
| 83 kCoverageISC_SecondaryOutputType, | |
| 84 | |
| 85 kSecondaryOutputTypeCnt, | |
| 86 }; | |
| 87 | |
| 80 // Specifies where the initial color comes from before the stages are applie d. | 88 // Specifies where the initial color comes from before the stages are applie d. |
| 81 enum ColorInput { | 89 enum ColorInput { |
| 82 kAllOnes_ColorInput, | 90 kAllOnes_ColorInput, |
| 83 kAttribute_ColorInput, | 91 kAttribute_ColorInput, |
| 84 kUniform_ColorInput, | 92 kUniform_ColorInput, |
| 85 | 93 |
| 86 kColorInputCnt | 94 kColorInputCnt |
| 87 }; | 95 }; |
| 88 | 96 |
| 89 struct KeyHeader { | 97 struct KeyHeader { |
| 90 uint8_t fDstReadKey; // set by GrGLShaderBuil der if there | 98 uint8_t fDstReadKey; // set by GrGLShaderBuil der if there |
|
bsalomon
2014/10/23 18:10:30
Not broken by your change, but the alignment in he
| |
| 91 // are effects that must read the dst. | 99 // are effects that must read the dst. |
| 92 // Otherwise, 0. | 100 // Otherwise, 0. |
| 93 uint8_t fFragPosKey; // set by GrGLShaderBuil der if there are | 101 uint8_t fFragPosKey; // set by GrGLShaderBuil der if there are |
| 94 // effects that read the fragment position. | 102 // effects that read the fragment position. |
| 95 // Otherwise, 0. | 103 // Otherwise, 0. |
| 96 | 104 |
| 97 SkBool8 fUseFragShaderOnly; | |
| 98 SkBool8 fEmitsPointSize; | 105 SkBool8 fEmitsPointSize; |
| 99 | 106 |
| 100 ColorInput fColorInput : 8; | 107 ColorInput fColorInput : 8; |
| 101 ColorInput fCoverageInput : 8; | 108 ColorInput fCoverageInput : 8; |
| 102 | 109 |
| 103 GrOptDrawState::PrimaryOutputType fPrimaryOutputType : 8; | 110 PrimaryOutputType fPrimaryOutputType : 8; |
| 104 GrOptDrawState::SecondaryOutputType fSecondaryOutputType : 8; | 111 SecondaryOutputType fSecondaryOutputType : 8; |
| 105 | 112 |
| 106 int8_t fPositionAttributeIndex; | 113 int8_t fPositionAttributeIndex; |
| 107 int8_t fLocalCoordAttributeIndex; | 114 int8_t fLocalCoordAttributeIndex; |
| 108 int8_t fColorAttributeIndex; | 115 int8_t fColorAttributeIndex; |
| 109 int8_t fCoverageAttributeIndex; | 116 int8_t fCoverageAttributeIndex; |
| 110 | 117 |
| 111 SkBool8 fHasGeometryProcessor; | 118 SkBool8 fHasGeometryProcessor; |
| 112 int8_t fColorEffectCnt; | 119 int8_t fColorEffectCnt; |
| 113 int8_t fCoverageEffectCnt; | 120 int8_t fCoverageEffectCnt; |
| 114 }; | 121 }; |
| 115 | 122 |
| 116 // The key, stored in fKey, is composed of five parts: | |
| 117 // 1. uint32_t for total key length. | |
| 118 // 2. uint32_t for a checksum. | |
| 119 // 3. Header struct defined above. | |
| 120 // 4. An array of offsets to effect keys and their sizes (see 5). uint16_t f or each | |
| 121 // offset and size. | |
| 122 // 5. per-effect keys. Each effect's key is a variable length array of uint3 2_t. | |
| 123 enum { | |
| 124 // Part 1. | |
| 125 kLengthOffset = 0, | |
| 126 // Part 2. | |
| 127 kChecksumOffset = kLengthOffset + sizeof(uint32_t), | |
| 128 // Part 3. | |
| 129 kHeaderOffset = kChecksumOffset + sizeof(uint32_t), | |
| 130 kHeaderSize = SkAlign4(sizeof(KeyHeader)), | |
| 131 // Part 4. | |
| 132 // This is the offset in the overall key to the array of per-effect offs et,length pairs. | |
| 133 kEffectKeyOffsetsAndLengthOffset = kHeaderOffset + kHeaderSize, | |
| 134 }; | |
| 135 | 123 |
| 136 template<typename T, size_t OFFSET> T* atOffset() { | 124 bool hasGeometryProcessor() const { |
| 137 return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(fKey.begin()) + O FFSET); | 125 return SkToBool(this->header().fHasGeometryProcessor); |
| 138 } | 126 } |
| 139 | 127 |
| 140 template<typename T, size_t OFFSET> const T* atOffset() const { | 128 int numColorEffects() const { |
| 141 return reinterpret_cast<const T*>(reinterpret_cast<intptr_t>(fKey.begin( )) + OFFSET); | 129 return this->header().fColorEffectCnt; |
| 142 } | 130 } |
| 143 | 131 |
| 144 KeyHeader* header() { return this->atOffset<KeyHeader, kHeaderOffset>(); } | 132 int numCoverageEffects() const { |
| 133 return this->header().fCoverageEffectCnt; | |
| 134 } | |
| 145 | 135 |
| 146 // a helper class to handle getting an individual processor's key | 136 int numTotalEffects() const { return this->numColorEffects() + this->numCove rageEffects(); } |
| 147 template <class ProcessorKeyBuilder> | |
| 148 static bool BuildStagedProcessorKey(const typename ProcessorKeyBuilder::Stag edProcessor& stage, | |
| 149 const GrGLCaps& caps, | |
| 150 bool requiresLocalCoordAttrib, | |
| 151 GrGLProgramDesc* desc, | |
| 152 int* offsetAndSizeIndex); | |
| 153 void finalize(); | |
| 154 | 137 |
| 155 const KeyHeader& getHeader() const { return *this->atOffset<KeyHeader, kHead erOffset>(); } | 138 // This should really only be used internally, base classes should return th eir own headers |
| 139 const KeyHeader& header() const { return *this->atOffset<KeyHeader, kHeaderO ffset>(); } | |
| 156 | 140 |
| 157 /** Used to provide effects' keys to their emitCode() function. */ | 141 /** Used to provide effects' keys to their emitCode() function. */ |
| 158 class ProcKeyProvider { | 142 class ProcKeyProvider { |
| 159 public: | 143 public: |
| 160 enum ProcessorType { | 144 enum ProcessorType { |
| 161 kGeometry_ProcessorType, | 145 kGeometry_ProcessorType, |
| 162 kFragment_ProcessorType, | 146 kFragment_ProcessorType, |
| 163 }; | 147 }; |
| 164 | 148 |
| 165 ProcKeyProvider(const GrGLProgramDesc* desc, ProcessorType type) | 149 ProcKeyProvider(const GrProgramDesc* desc, ProcessorType type, int effec tOffset) |
| 166 : fDesc(desc), fBaseIndex(0) { | 150 : fDesc(desc), fBaseIndex(0), fEffectOffset(effectOffset) { |
| 167 switch (type) { | 151 switch (type) { |
| 168 case kGeometry_ProcessorType: | 152 case kGeometry_ProcessorType: |
| 169 // there can be only one | 153 // there can be only one |
| 170 fBaseIndex = 0; | 154 fBaseIndex = 0; |
| 171 break; | 155 break; |
| 172 case kFragment_ProcessorType: | 156 case kFragment_ProcessorType: |
| 173 fBaseIndex = desc->hasGeometryProcessor() ? 1 : 0; | 157 fBaseIndex = desc->hasGeometryProcessor() ? 1 : 0; |
| 174 break; | 158 break; |
| 175 } | 159 } |
| 176 } | 160 } |
| 177 | 161 |
| 178 GrProcessorKey get(int index) const { | 162 GrProcessorKey get(int index) const { |
| 179 const uint16_t* offsetsAndLengths = reinterpret_cast<const uint16_t* >( | 163 const uint16_t* offsetsAndLengths = reinterpret_cast<const uint16_t* >( |
| 180 fDesc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset); | 164 fDesc->fKey.begin() + fEffectOffset); |
| 181 // We store two uint16_ts per effect, one for the offset to the effe ct's key and one for | 165 // We store two uint16_ts per effect, one for the offset to the effe ct's key and one for |
| 182 // its length. Here we just need the offset. | 166 // its length. Here we just need the offset. |
| 183 uint16_t offset = offsetsAndLengths[2 * (fBaseIndex + index) + 0]; | 167 uint16_t offset = offsetsAndLengths[2 * (fBaseIndex + index) + 0]; |
| 184 uint16_t length = offsetsAndLengths[2 * (fBaseIndex + index) + 1]; | 168 uint16_t length = offsetsAndLengths[2 * (fBaseIndex + index) + 1]; |
| 185 // Currently effects must add to the key in units of uint32_t. | 169 // Currently effects must add to the key in units of uint32_t. |
| 186 SkASSERT(0 == (length % sizeof(uint32_t))); | 170 SkASSERT(0 == (length % sizeof(uint32_t))); |
| 187 return GrProcessorKey(reinterpret_cast<const uint32_t*>(fDesc->fKey. begin() + offset), | 171 return GrProcessorKey(reinterpret_cast<const uint32_t*>(fDesc->fKey. begin() + offset), |
| 188 length / sizeof(uint32_t)); | 172 length / sizeof(uint32_t)); |
| 189 } | 173 } |
| 190 private: | 174 private: |
| 191 const GrGLProgramDesc* fDesc; | 175 const GrProgramDesc* fDesc; |
| 192 int fBaseIndex; | 176 int fBaseIndex; |
| 177 int fEffectOffset; | |
| 178 }; | |
| 179 | |
| 180 protected: | |
| 181 | |
| 182 template<typename T, size_t OFFSET> T* atOffset() { | |
| 183 return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(fKey.begin()) + O FFSET); | |
| 184 } | |
| 185 | |
| 186 template<typename T, size_t OFFSET> const T* atOffset() const { | |
| 187 return reinterpret_cast<const T*>(reinterpret_cast<intptr_t>(fKey.begin( )) + OFFSET); | |
| 188 } | |
| 189 // The key, stored in fKey, is composed of five parts: | |
| 190 // 1. uint32_t for total key length. | |
| 191 // 2. uint32_t for a checksum. | |
| 192 // 3. Header struct defined above., also room for derived class headers. | |
| 193 // 4. An array of offsets to effect keys and their sizes (see 5). uint16_t f or each | |
| 194 // offset and size. | |
| 195 // 5. per-effect keys. Each effect's key is a variable length array of uint3 2_t. | |
| 196 enum KeyOffsets { | |
| 197 // Part 1. | |
| 198 kLengthOffset = 0, | |
| 199 // Part 2. | |
| 200 kChecksumOffset = kLengthOffset + sizeof(uint32_t), | |
| 201 // Part 3. | |
| 202 kHeaderOffset = kChecksumOffset + sizeof(uint32_t), | |
| 203 kHeaderSize = SkAlign4(2 * sizeof(KeyHeader)), | |
| 204 // Part 4. | |
| 205 // This is the offset in the overall key to the array of per-effect offs et,length pairs. | |
| 206 kEffectKeyOffsetsAndLengthOffset = kHeaderOffset + kHeaderSize, | |
| 193 }; | 207 }; |
| 194 | 208 |
| 195 enum { | 209 enum { |
| 196 kMaxPreallocEffects = 8, | 210 kMaxPreallocEffects = 8, |
| 197 kIntsPerEffect = 4, // This is an overestimate of the average ef fect key size. | 211 kIntsPerEffect = 4, // This is an overestimate of the average ef fect key size. |
| 198 kPreAllocSize = kEffectKeyOffsetsAndLengthOffset + | 212 kPreAllocSize = kEffectKeyOffsetsAndLengthOffset + |
| 199 kMaxPreallocEffects * sizeof(uint32_t) * kIntsPerEffect, | 213 kMaxPreallocEffects * sizeof(uint32_t) * kIntsPerEffect, |
| 200 }; | 214 }; |
| 201 | 215 |
| 202 SkSTArray<kPreAllocSize, uint8_t, true> fKey; | 216 SkSTArray<kPreAllocSize, uint8_t, true> fKey; |
| 203 | 217 |
| 204 // GrGLProgram and GrGLShaderBuilder read the private fields to generate cod e. TODO: Split out | 218 friend class GrGLProgramDesc; |
| 205 // part of GrGLShaderBuilder that is used by effects so that this header doe sn't need to be | |
| 206 // visible to GrGLProcessors. Then make public accessors as necessary and re move friends. | |
| 207 friend class GrGLProgram; | |
| 208 friend class GrGLProgramBuilder; | |
| 209 friend class GrGLLegacyNvprProgramBuilder; | |
| 210 friend class GrGLVertexBuilder; | |
| 211 friend class GrGLFragmentShaderBuilder; | |
| 212 friend class GrGLGeometryBuilder; | |
| 213 }; | 219 }; |
| 214 | 220 |
| 215 #endif | 221 #endif |
| OLD | NEW |