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 "GrGLProcessor.h" | 11 #include "GrColor.h" |
12 #include "GrDrawState.h" | 12 #include "GrProgramDesc.h" |
13 #include "GrGpu.h" | 13 #include "GrGpu.h" |
14 #include "GrOptDrawState.h" | 14 #include "GrTypesPriv.h" |
15 | 15 |
16 class GrGpuGL; | 16 class GrGpuGL; |
17 | 17 |
18 /** This class describes a program to generate. It also serves as a program cach
e key. Very little | 18 /** |
19 of this is GL-specific. The GL-specific parts could be factored out into a s
ubclass. */ | 19 * This class can be used to build a GrProgramDesc. It also provides helpers fo
r accessing |
20 class GrGLProgramDesc { | 20 * GL specific info in the header. |
| 21 */ |
| 22 class GrGLProgramDescBuilder { |
21 public: | 23 public: |
22 GrGLProgramDesc() {} | 24 struct GLKeyHeader : public GrProgramDesc::KeyHeader { |
23 GrGLProgramDesc(const GrGLProgramDesc& desc) { *this = desc; } | 25 SkBool8 fUseNvpr; |
24 | |
25 // Returns this as a uint32_t array to be used as a key in the program cache
. | |
26 const uint32_t* asKey() const { | |
27 return reinterpret_cast<const uint32_t*>(fKey.begin()); | |
28 } | |
29 | |
30 // 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 | |
32 // 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>
(); } | |
34 | |
35 // 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>(); } | |
37 | |
38 /** | |
39 * Builds a program descriptor from a GrOptDrawState. Whether the primitive
type is points, and | |
40 * the caps of the GrGpuGL are also inputs. It also outputs the color and co
verage stages | |
41 * referenced by the generated descriptor. Coverage stages from the drawStat
e may be treated as | |
42 * color stages in the output. | |
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 } | |
53 | |
54 int numColorEffects() 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. | |
68 return 0 == memcmp(this->asKey(), other.asKey(), this->keyLength() & ~0x
3); | |
69 } | |
70 | |
71 bool operator!= (const GrGLProgramDesc& other) const { | |
72 return !(*this == other); | |
73 } | |
74 | |
75 static bool Less(const GrGLProgramDesc& a, const GrGLProgramDesc& b) { | |
76 return memcmp(a.asKey(), b.asKey(), a.keyLength() & ~0x3) < 0; | |
77 } | |
78 | |
79 private: | |
80 // Specifies where the initial color comes from before the stages are applie
d. | |
81 enum ColorInput { | |
82 kAllOnes_ColorInput, | |
83 kAttribute_ColorInput, | |
84 kUniform_ColorInput, | |
85 | |
86 kColorInputCnt | |
87 }; | 26 }; |
88 | 27 |
89 struct KeyHeader { | 28 // The key, stored in fKey, is composed of five parts(first 2 are defined in
the key itself): |
90 uint8_t fDstReadKey; // set by GrGLShaderBuil
der if there | |
91 // are effects that must
read the dst. | |
92 // Otherwise, 0. | |
93 uint8_t fFragPosKey; // set by GrGLShaderBuil
der if there are | |
94 // effects that read the
fragment position. | |
95 // Otherwise, 0. | |
96 | |
97 SkBool8 fUseNvpr; | |
98 SkBool8 fEmitsPointSize; | |
99 | |
100 ColorInput fColorInput : 8; | |
101 ColorInput fCoverageInput : 8; | |
102 | |
103 GrOptDrawState::PrimaryOutputType fPrimaryOutputType : 8; | |
104 GrOptDrawState::SecondaryOutputType fSecondaryOutputType : 8; | |
105 | |
106 int8_t fPositionAttributeIndex; | |
107 int8_t fLocalCoordAttributeIndex; | |
108 int8_t fColorAttributeIndex; | |
109 int8_t fCoverageAttributeIndex; | |
110 | |
111 SkBool8 fHasGeometryProcessor; | |
112 int8_t fColorEffectCnt; | |
113 int8_t fCoverageEffectCnt; | |
114 }; | |
115 | |
116 // The key, stored in fKey, is composed of five parts: | |
117 // 1. uint32_t for total key length. | 29 // 1. uint32_t for total key length. |
118 // 2. uint32_t for a checksum. | 30 // 2. uint32_t for a checksum. |
119 // 3. Header struct defined above. | 31 // 3. Header struct defined above. |
120 // 4. An array of offsets to effect keys and their sizes (see 5). uint16_t f
or each | 32 // 4. An array of offsets to effect keys and their sizes (see 5). uint16_t f
or each |
121 // offset and size. | 33 // offset and size. |
122 // 5. per-effect keys. Each effect's key is a variable length array of uint3
2_t. | 34 // 5. per-effect keys. Each effect's key is a variable length array of uint3
2_t. |
123 enum { | 35 enum { |
124 // Part 1. | |
125 kLengthOffset = 0, | |
126 // Part 2. | |
127 kChecksumOffset = kLengthOffset + sizeof(uint32_t), | |
128 // Part 3. | 36 // Part 3. |
129 kHeaderOffset = kChecksumOffset + sizeof(uint32_t), | 37 kHeaderOffset = GrProgramDesc::kHeaderOffset, |
130 kHeaderSize = SkAlign4(sizeof(KeyHeader)), | 38 kHeaderSize = SkAlign4(sizeof(GLKeyHeader)), |
131 // Part 4. | 39 // Part 4. |
132 // This is the offset in the overall key to the array of per-effect offs
et,length pairs. | 40 // This is the offset in the overall key to the array of per-effect offs
et,length pairs. |
133 kEffectKeyOffsetsAndLengthOffset = kHeaderOffset + kHeaderSize, | 41 kProcessorKeyOffsetsAndLengthOffset = kHeaderOffset + kHeaderSize, |
134 }; | 42 }; |
135 | 43 |
136 template<typename T, size_t OFFSET> T* atOffset() { | 44 /** |
137 return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(fKey.begin()) + O
FFSET); | 45 * Builds a GL specific program descriptor |
| 46 * |
| 47 * @param GrOptDrawState The optimized drawstate. The descriptor will repr
esent a program |
| 48 * which this optstate can use to draw with. The opt
state contains |
| 49 * general draw information, as well as the specific
color, geometry, |
| 50 * and coverage stages which will be used to generate
the GL Program for |
| 51 * this optstate. |
| 52 * @param DescInfo A descriptor info struct, generated by the optstate, whi
ch contains a number |
| 53 * of important facts about the program the built descripto
r will represent |
| 54 * @param DrawType |
| 55 * @param GrGpuGL A GL Gpu, the caps and Gpu object are used to output proc
essor specific |
| 56 * parts of the descriptor. |
| 57 * @param GrDeviceCoordTexture A dstCopy texture, which may be null if fram
e buffer fetch is |
| 58 * supported |
| 59 * @param GrProgramDesc The built and finalized descriptor |
| 60 **/ |
| 61 static bool Build(const GrOptDrawState&, |
| 62 const GrProgramDesc::DescInfo&, |
| 63 GrGpu::DrawType, |
| 64 GrGpuGL*, |
| 65 const GrDeviceCoordTexture*, |
| 66 GrProgramDesc*); |
| 67 |
| 68 static const GLKeyHeader& GetHeader(const GrProgramDesc& desc) { |
| 69 return *desc.atOffset<GLKeyHeader, kHeaderOffset>(); |
138 } | 70 } |
139 | 71 |
140 template<typename T, size_t OFFSET> const T* atOffset() const { | 72 private: |
141 return reinterpret_cast<const T*>(reinterpret_cast<intptr_t>(fKey.begin(
)) + OFFSET); | |
142 } | |
143 | |
144 KeyHeader* header() { return this->atOffset<KeyHeader, kHeaderOffset>(); } | |
145 | |
146 // a helper class to handle getting an individual processor's key | |
147 template <class ProcessorKeyBuilder> | 73 template <class ProcessorKeyBuilder> |
148 static bool BuildStagedProcessorKey(const typename ProcessorKeyBuilder::Stag
edProcessor& stage, | 74 static bool BuildStagedProcessorKey(const typename ProcessorKeyBuilder::Stag
edProcessor& stage, |
149 const GrGLCaps& caps, | 75 const GrGLCaps& caps, |
150 bool requiresLocalCoordAttrib, | 76 bool requiresLocalCoordAttrib, |
151 GrGLProgramDesc* desc, | 77 GrProgramDesc* desc, |
152 int* offsetAndSizeIndex); | 78 int* offsetAndSizeIndex); |
153 void finalize(); | |
154 | |
155 const KeyHeader& getHeader() const { return *this->atOffset<KeyHeader, kHead
erOffset>(); } | |
156 | |
157 /** Used to provide effects' keys to their emitCode() function. */ | |
158 class ProcKeyProvider { | |
159 public: | |
160 enum ProcessorType { | |
161 kGeometry_ProcessorType, | |
162 kFragment_ProcessorType, | |
163 }; | |
164 | |
165 ProcKeyProvider(const GrGLProgramDesc* desc, ProcessorType type) | |
166 : fDesc(desc), fBaseIndex(0) { | |
167 switch (type) { | |
168 case kGeometry_ProcessorType: | |
169 // there can be only one | |
170 fBaseIndex = 0; | |
171 break; | |
172 case kFragment_ProcessorType: | |
173 fBaseIndex = desc->hasGeometryProcessor() ? 1 : 0; | |
174 break; | |
175 } | |
176 } | |
177 | |
178 GrProcessorKey get(int index) const { | |
179 const uint16_t* offsetsAndLengths = reinterpret_cast<const uint16_t*
>( | |
180 fDesc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset); | |
181 // 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. | |
183 uint16_t offset = offsetsAndLengths[2 * (fBaseIndex + index) + 0]; | |
184 uint16_t length = offsetsAndLengths[2 * (fBaseIndex + index) + 1]; | |
185 // Currently effects must add to the key in units of uint32_t. | |
186 SkASSERT(0 == (length % sizeof(uint32_t))); | |
187 return GrProcessorKey(reinterpret_cast<const uint32_t*>(fDesc->fKey.
begin() + offset), | |
188 length / sizeof(uint32_t)); | |
189 } | |
190 private: | |
191 const GrGLProgramDesc* fDesc; | |
192 int fBaseIndex; | |
193 }; | |
194 | |
195 enum { | |
196 kMaxPreallocEffects = 8, | |
197 kIntsPerEffect = 4, // This is an overestimate of the average ef
fect key size. | |
198 kPreAllocSize = kEffectKeyOffsetsAndLengthOffset + | |
199 kMaxPreallocEffects * sizeof(uint32_t) * kIntsPerEffect, | |
200 }; | |
201 | |
202 SkSTArray<kPreAllocSize, uint8_t, true> fKey; | |
203 | |
204 // GrGLProgram and GrGLShaderBuilder read the private fields to generate cod
e. TODO: Split out | |
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 }; | 79 }; |
214 | 80 |
215 #endif | 81 #endif |
OLD | NEW |