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