blob: 4056c77808750f97620e30f2e1ab0119a6edfa71 [file] [log] [blame]
bsalomon@google.com798c8c42013-03-27 19:50:27 +00001/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
joshualitt30ba4362014-08-21 20:18:45 -07008#include "gl/builders/GrGLProgramBuilder.h"
bsalomon@google.com798c8c42013-03-27 19:50:27 +00009#include "GrGLProgramDesc.h"
10#include "GrBackendEffectFactory.h"
bsalomon@google.com798c8c42013-03-27 19:50:27 +000011#include "GrEffect.h"
12#include "GrGpuGL.h"
13
bsalomon@google.com2db3ded2013-05-22 14:34:04 +000014#include "SkChecksum.h"
15
bsalomon929f29a2014-07-17 07:55:11 -070016bool GrGLProgramDesc::GetEffectKeyAndUpdateStats(const GrEffectStage& stage,
17 const GrGLCaps& caps,
18 bool useExplicitLocalCoords,
19 GrEffectKeyBuilder* b,
20 uint16_t* effectKeySize,
21 bool* setTrueIfReadsDst,
22 bool* setTrueIfReadsPos,
kkinnunenec56e452014-08-25 22:21:16 -070023 bool* setTrueIfRequiresVertexShader) {
bsalomon848faf02014-07-11 10:01:02 -070024 const GrBackendEffectFactory& factory = stage.getEffect()->getFactory();
joshualitt49586be2014-09-16 08:21:41 -070025 const GrEffect& effect = *stage.getEffect();
26 if (effect.willReadDstColor()) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000027 *setTrueIfReadsDst = true;
28 }
joshualitt49586be2014-09-16 08:21:41 -070029 if (effect.willReadFragmentPosition()) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000030 *setTrueIfReadsPos = true;
31 }
joshualitt49586be2014-09-16 08:21:41 -070032 if (effect.requiresVertexShader()) {
kkinnunenec56e452014-08-25 22:21:16 -070033 *setTrueIfRequiresVertexShader = true;
commit-bot@chromium.org234d4fb2013-09-30 19:55:49 +000034 }
joshualitt49586be2014-09-16 08:21:41 -070035 factory.getGLEffectKey(effect, caps, b);
bsalomon929f29a2014-07-17 07:55:11 -070036 size_t size = b->size();
37 if (size > SK_MaxU16) {
38 *effectKeySize = 0; // suppresses a warning.
39 return false;
40 }
41 *effectKeySize = SkToU16(size);
joshualitt49586be2014-09-16 08:21:41 -070042 if (!GrGLProgramEffects::GenEffectMetaKey(stage,
43 useExplicitLocalCoords,
44 caps,
45 b)) {
bsalomon929f29a2014-07-17 07:55:11 -070046 return false;
47 }
48 return true;
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000049}
bsalomon848faf02014-07-11 10:01:02 -070050
egdaniel8a4c1032014-09-16 07:18:54 -070051bool GrGLProgramDesc::Build(const GrDrawState& drawState,
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +000052 GrGpu::DrawType drawType,
egdaniel8a4c1032014-09-16 07:18:54 -070053 GrDrawState::BlendOptFlags blendOpts,
bsalomon@google.com798c8c42013-03-27 19:50:27 +000054 GrBlendCoeff srcCoeff,
55 GrBlendCoeff dstCoeff,
56 const GrGpuGL* gpu,
bsalomon@google.com26e18b52013-03-29 19:22:36 +000057 const GrDeviceCoordTexture* dstCopy,
joshualittbd769d02014-09-04 08:56:46 -070058 const GrEffectStage** geometryProcessor,
bsalomon@google.com2c84aa32013-06-06 20:28:57 +000059 SkTArray<const GrEffectStage*, true>* colorStages,
60 SkTArray<const GrEffectStage*, true>* coverageStages,
bsalomon@google.com798c8c42013-03-27 19:50:27 +000061 GrGLProgramDesc* desc) {
bsalomon@google.com2c84aa32013-06-06 20:28:57 +000062 colorStages->reset();
63 coverageStages->reset();
64
egdaniel8a4c1032014-09-16 07:18:54 -070065 // This should already have been caught
66 SkASSERT(!(GrDrawState::kSkipDraw_BlendOptFlag & blendOpts));
67
68 bool skipCoverage = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag);
69
70 bool skipColor = SkToBool(blendOpts & (GrDrawState::kEmitTransBlack_BlendOptFlag |
71 GrDrawState::kEmitCoverage_BlendOptFlag));
72
73 int firstEffectiveColorStage = 0;
74 bool inputColorIsUsed = true;
75
76 if (!skipColor) {
77 firstEffectiveColorStage = drawState.numColorStages();
78 while (firstEffectiveColorStage > 0 && inputColorIsUsed) {
79 --firstEffectiveColorStage;
80 const GrEffect* effect = drawState.getColorStage(firstEffectiveColorStage).getEffect();
81 inputColorIsUsed = effect->willUseInputColor();
82 }
83 }
84
85 int firstEffectiveCoverageStage = 0;
86 bool inputCoverageIsUsed = true;
87 if (!skipCoverage) {
88 firstEffectiveCoverageStage = drawState.numCoverageStages();
89 while (firstEffectiveCoverageStage > 0 && inputCoverageIsUsed) {
90 --firstEffectiveCoverageStage;
91 const GrEffect* effect = drawState.getCoverageStage(firstEffectiveCoverageStage).getEffect();
92 inputCoverageIsUsed = effect->willUseInputColor();
93 }
94 }
bsalomon@google.com798c8c42013-03-27 19:50:27 +000095
96 // The descriptor is used as a cache key. Thus when a field of the
97 // descriptor will not affect program generation (because of the attribute
98 // bindings in use or other descriptor field settings) it should be set
99 // to a canonical value to avoid duplicate programs with different keys.
100
egdaniel8a4c1032014-09-16 07:18:54 -0700101 bool requiresColorAttrib = !skipColor && drawState.hasColorVertexAttribute();
102 bool requiresCoverageAttrib = !skipCoverage && drawState.hasCoverageVertexAttribute();
jvanverth@google.com054ae992013-04-01 20:06:51 +0000103 // we only need the local coords if we're actually going to generate effect code
egdaniel8a4c1032014-09-16 07:18:54 -0700104 bool requiresLocalCoordAttrib = !(skipCoverage && skipColor) &&
105 drawState.hasLocalCoordAttribute();
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000106
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000107 bool readsDst = false;
bsalomon@google.comb5158812013-05-13 18:50:25 +0000108 bool readFragPosition = false;
kkinnunenec56e452014-08-25 22:21:16 -0700109
110 // Provide option for shader programs without vertex shader only when drawing paths.
111 bool requiresVertexShader = !GrGpu::IsPathRenderingDrawType(drawType);
112
egdaniel8a4c1032014-09-16 07:18:54 -0700113 int numStages = 0;
114 if (drawState.hasGeometryProcessor()) {
115 numStages++;
116 }
117 if (!skipColor) {
118 numStages += drawState.numColorStages() - firstEffectiveColorStage;
119 }
120 if (!skipCoverage) {
121 numStages += drawState.numCoverageStages() - firstEffectiveCoverageStage;
122 }
bsalomon929f29a2014-07-17 07:55:11 -0700123 GR_STATIC_ASSERT(0 == kEffectKeyOffsetsAndLengthOffset % sizeof(uint32_t));
bsalomon848faf02014-07-11 10:01:02 -0700124 // Make room for everything up to and including the array of offsets to effect keys.
125 desc->fKey.reset();
bsalomon929f29a2014-07-17 07:55:11 -0700126 desc->fKey.push_back_n(kEffectKeyOffsetsAndLengthOffset + 2 * sizeof(uint16_t) * numStages);
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000127
bsalomon929f29a2014-07-17 07:55:11 -0700128 int offsetAndSizeIndex = 0;
bsalomon848faf02014-07-11 10:01:02 -0700129 bool effectKeySuccess = true;
joshualittbd769d02014-09-04 08:56:46 -0700130
131 KeyHeader* header = desc->header();
132 // make sure any padding in the header is zeroed.
133 memset(desc->header(), 0, kHeaderSize);
134
135 // We can only have one effect which touches the vertex shader
egdaniel8a4c1032014-09-16 07:18:54 -0700136 if (drawState.hasGeometryProcessor()) {
joshualittbd769d02014-09-04 08:56:46 -0700137 uint16_t* offsetAndSize =
bsalomon929f29a2014-07-17 07:55:11 -0700138 reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
139 offsetAndSizeIndex * 2 * sizeof(uint16_t));
bsalomon848faf02014-07-11 10:01:02 -0700140
141 GrEffectKeyBuilder b(&desc->fKey);
bsalomon929f29a2014-07-17 07:55:11 -0700142 uint16_t effectKeySize;
143 uint32_t effectOffset = desc->fKey.count();
144 effectKeySuccess |= GetEffectKeyAndUpdateStats(
egdaniel8a4c1032014-09-16 07:18:54 -0700145 *drawState.getGeometryProcessor(), gpu->glCaps(),
bsalomon929f29a2014-07-17 07:55:11 -0700146 requiresLocalCoordAttrib, &b,
147 &effectKeySize, &readsDst,
kkinnunenec56e452014-08-25 22:21:16 -0700148 &readFragPosition, &requiresVertexShader);
bsalomon929f29a2014-07-17 07:55:11 -0700149 effectKeySuccess |= (effectOffset <= SK_MaxU16);
150
151 offsetAndSize[0] = SkToU16(effectOffset);
152 offsetAndSize[1] = effectKeySize;
153 ++offsetAndSizeIndex;
egdaniel8a4c1032014-09-16 07:18:54 -0700154 *geometryProcessor = drawState.getGeometryProcessor();
joshualittbd769d02014-09-04 08:56:46 -0700155 SkASSERT(requiresVertexShader);
156 header->fHasGeometryProcessor = true;
157 }
158
egdaniel8a4c1032014-09-16 07:18:54 -0700159 if (!skipColor) {
160 for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
161 uint16_t* offsetAndSize =
162 reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
163 offsetAndSizeIndex * 2 * sizeof(uint16_t));
joshualittbd769d02014-09-04 08:56:46 -0700164
egdaniel8a4c1032014-09-16 07:18:54 -0700165 bool effectRequiresVertexShader = false;
166 GrEffectKeyBuilder b(&desc->fKey);
167 uint16_t effectKeySize;
168 uint32_t effectOffset = desc->fKey.count();
169 effectKeySuccess |= GetEffectKeyAndUpdateStats(
170 drawState.getColorStage(s), gpu->glCaps(),
171 requiresLocalCoordAttrib, &b,
172 &effectKeySize, &readsDst,
173 &readFragPosition, &effectRequiresVertexShader);
174 effectKeySuccess |= (effectOffset <= SK_MaxU16);
joshualittbd769d02014-09-04 08:56:46 -0700175
egdaniel8a4c1032014-09-16 07:18:54 -0700176 offsetAndSize[0] = SkToU16(effectOffset);
177 offsetAndSize[1] = effectKeySize;
178 ++offsetAndSizeIndex;
179 SkASSERT(!effectRequiresVertexShader);
180 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000181 }
egdaniel8a4c1032014-09-16 07:18:54 -0700182 if (!skipCoverage) {
183 for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) {
184 uint16_t* offsetAndSize =
185 reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
186 offsetAndSizeIndex * 2 * sizeof(uint16_t));
bsalomon929f29a2014-07-17 07:55:11 -0700187
egdaniel8a4c1032014-09-16 07:18:54 -0700188 bool effectRequiresVertexShader = false;
189 GrEffectKeyBuilder b(&desc->fKey);
190 uint16_t effectKeySize;
191 uint32_t effectOffset = desc->fKey.count();
192 effectKeySuccess |= GetEffectKeyAndUpdateStats(
193 drawState.getCoverageStage(s), gpu->glCaps(),
194 requiresLocalCoordAttrib, &b,
195 &effectKeySize, &readsDst,
196 &readFragPosition, &effectRequiresVertexShader);
197 effectKeySuccess |= (effectOffset <= SK_MaxU16);
bsalomon929f29a2014-07-17 07:55:11 -0700198
egdaniel8a4c1032014-09-16 07:18:54 -0700199 offsetAndSize[0] = SkToU16(effectOffset);
200 offsetAndSize[1] = effectKeySize;
201 ++offsetAndSizeIndex;
202 SkASSERT(!effectRequiresVertexShader);
203 }
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000204 }
bsalomon848faf02014-07-11 10:01:02 -0700205 if (!effectKeySuccess) {
206 desc->fKey.reset();
207 return false;
208 }
209
bsalomon848faf02014-07-11 10:01:02 -0700210 // Because header is a pointer into the dynamic array, we can't push any new data into the key
211 // below here.
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000212
kkinnunenec56e452014-08-25 22:21:16 -0700213 header->fRequiresVertexShader = requiresVertexShader || requiresLocalCoordAttrib;
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000214 header->fEmitsPointSize = GrGpu::kDrawPoints_DrawType == drawType;
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000215
216 // Currently the experimental GS will only work with triangle prims (and it doesn't do anything
217 // other than pass through values from the VS to the FS anyway).
218#if GR_GL_EXPERIMENTAL_GS
219#if 0
220 header->fExperimentalGS = gpu->caps().geometryShaderSupport();
221#else
222 header->fExperimentalGS = false;
223#endif
224#endif
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000225 bool defaultToUniformInputs = GR_GL_NO_CONSTANT_ATTRIBUTES || gpu->caps()->pathRenderingSupport();
226
egdaniel8a4c1032014-09-16 07:18:54 -0700227 if (!inputColorIsUsed && !skipColor) {
egdaniel842b0862014-09-02 10:01:30 -0700228 header->fColorInput = kAllOnes_ColorInput;
egdaniel8a4c1032014-09-16 07:18:54 -0700229 } else if (defaultToUniformInputs && !requiresColorAttrib && inputColorIsUsed) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000230 header->fColorInput = kUniform_ColorInput;
231 } else {
232 header->fColorInput = kAttribute_ColorInput;
kkinnunenec56e452014-08-25 22:21:16 -0700233 header->fRequiresVertexShader = true;
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000234 }
235
egdaniel8a4c1032014-09-16 07:18:54 -0700236 bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverageColor();
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000237
egdaniel8a4c1032014-09-16 07:18:54 -0700238 if ((covIsSolidWhite || !inputCoverageIsUsed) && !skipCoverage) {
egdaniel842b0862014-09-02 10:01:30 -0700239 header->fCoverageInput = kAllOnes_ColorInput;
egdaniel8a4c1032014-09-16 07:18:54 -0700240 } else if (defaultToUniformInputs && !requiresCoverageAttrib && inputCoverageIsUsed) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000241 header->fCoverageInput = kUniform_ColorInput;
242 } else {
243 header->fCoverageInput = kAttribute_ColorInput;
kkinnunenec56e452014-08-25 22:21:16 -0700244 header->fRequiresVertexShader = true;
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000245 }
246
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000247 if (readsDst) {
bsalomon49f085d2014-09-05 13:34:00 -0700248 SkASSERT(dstCopy || gpu->caps()->dstReadInShaderSupport());
bsalomon@google.com6b0cf022013-05-03 13:35:14 +0000249 const GrTexture* dstCopyTexture = NULL;
bsalomon49f085d2014-09-05 13:34:00 -0700250 if (dstCopy) {
bsalomon@google.com6b0cf022013-05-03 13:35:14 +0000251 dstCopyTexture = dstCopy->texture();
252 }
joshualitt30ba4362014-08-21 20:18:45 -0700253 header->fDstReadKey = GrGLFragmentShaderBuilder::KeyForDstRead(dstCopyTexture,
254 gpu->glCaps());
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000255 SkASSERT(0 != header->fDstReadKey);
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000256 } else {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000257 header->fDstReadKey = 0;
bsalomon@google.comb5158812013-05-13 18:50:25 +0000258 }
259
260 if (readFragPosition) {
joshualitt30ba4362014-08-21 20:18:45 -0700261 header->fFragPosKey = GrGLFragmentShaderBuilder::KeyForFragmentPosition(
egdaniel8a4c1032014-09-16 07:18:54 -0700262 drawState.getRenderTarget(), gpu->glCaps());
bsalomon@google.comb5158812013-05-13 18:50:25 +0000263 } else {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000264 header->fFragPosKey = 0;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000265 }
266
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000267 // Record attribute indices
egdaniel8a4c1032014-09-16 07:18:54 -0700268 header->fPositionAttributeIndex = drawState.positionAttributeIndex();
269 header->fLocalCoordAttributeIndex = drawState.localCoordAttributeIndex();
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +0000270
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000271 // For constant color and coverage we need an attribute with an index beyond those already set
egdaniel8a4c1032014-09-16 07:18:54 -0700272 int availableAttributeIndex = drawState.getVertexAttribCount();
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000273 if (requiresColorAttrib) {
egdaniel8a4c1032014-09-16 07:18:54 -0700274 header->fColorAttributeIndex = drawState.colorVertexAttributeIndex();
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000275 } else if (GrGLProgramDesc::kAttribute_ColorInput == header->fColorInput) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000276 SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000277 header->fColorAttributeIndex = availableAttributeIndex;
278 availableAttributeIndex++;
279 } else {
280 header->fColorAttributeIndex = -1;
281 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +0000282
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000283 if (requiresCoverageAttrib) {
egdaniel8a4c1032014-09-16 07:18:54 -0700284 header->fCoverageAttributeIndex = drawState.coverageVertexAttributeIndex();
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000285 } else if (GrGLProgramDesc::kAttribute_ColorInput == header->fCoverageInput) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000286 SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000287 header->fCoverageAttributeIndex = availableAttributeIndex;
288 } else {
289 header->fCoverageAttributeIndex = -1;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000290 }
291
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000292 // Here we deal with whether/how we handle color and coverage separately.
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +0000293
commit-bot@chromium.org8a135882014-02-05 16:29:12 +0000294 // Set this default and then possibly change our mind if there is coverage.
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000295 header->fCoverageOutput = kModulate_CoverageOutput;
296
297 // If we do have coverage determine whether it matters.
egdaniel8a4c1032014-09-16 07:18:54 -0700298 bool separateCoverageFromColor = drawState.hasGeometryProcessor();
299 if (!drawState.isCoverageDrawing() && !skipCoverage &&
300 (drawState.numCoverageStages() > 0 ||
301 drawState.hasGeometryProcessor() ||
joshualittbd769d02014-09-04 08:56:46 -0700302 requiresCoverageAttrib)) {
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000303
egdaniel8a4c1032014-09-16 07:18:54 -0700304 if (gpu->caps()->dualSourceBlendingSupport() &&
305 !(blendOpts & (GrDrawState::kEmitCoverage_BlendOptFlag |
306 GrDrawState::kCoverageAsAlpha_BlendOptFlag))) {
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000307 if (kZero_GrBlendCoeff == dstCoeff) {
308 // write the coverage value to second color
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000309 header->fCoverageOutput = kSecondaryCoverage_CoverageOutput;
310 separateCoverageFromColor = true;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000311 } else if (kSA_GrBlendCoeff == dstCoeff) {
312 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000313 header->fCoverageOutput = kSecondaryCoverageISA_CoverageOutput;
314 separateCoverageFromColor = true;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000315 } else if (kSC_GrBlendCoeff == dstCoeff) {
316 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000317 header->fCoverageOutput = kSecondaryCoverageISC_CoverageOutput;
318 separateCoverageFromColor = true;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000319 }
bsalomon@google.com5920ac22013-04-19 13:14:45 +0000320 } else if (readsDst &&
bsalomon@google.com0c89db22013-05-15 17:53:04 +0000321 kOne_GrBlendCoeff == srcCoeff &&
322 kZero_GrBlendCoeff == dstCoeff) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000323 header->fCoverageOutput = kCombineWithDst_CoverageOutput;
324 separateCoverageFromColor = true;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000325 }
326 }
joshualittbd769d02014-09-04 08:56:46 -0700327
egdaniel8a4c1032014-09-16 07:18:54 -0700328 if (!skipColor) {
329 for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
330 colorStages->push_back(&drawState.getColorStage(s));
331 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000332 }
egdaniel8a4c1032014-09-16 07:18:54 -0700333 if (!skipCoverage) {
334 SkTArray<const GrEffectStage*, true>* array;
335 if (separateCoverageFromColor) {
336 array = coverageStages;
337 } else {
338 array = colorStages;
339 }
340 for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) {
341 array->push_back(&drawState.getCoverageStage(s));
342 }
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000343 }
commit-bot@chromium.orga34995e2013-10-23 05:42:03 +0000344 header->fColorEffectCnt = colorStages->count();
345 header->fCoverageEffectCnt = coverageStages->count();
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000346
bsalomon848faf02014-07-11 10:01:02 -0700347 desc->finalize();
348 return true;
349}
350
351void GrGLProgramDesc::finalize() {
352 int keyLength = fKey.count();
353 SkASSERT(0 == (keyLength % 4));
354 *this->atOffset<uint32_t, kLengthOffset>() = SkToU32(keyLength);
355
356 uint32_t* checksum = this->atOffset<uint32_t, kChecksumOffset>();
357 *checksum = 0;
358 *checksum = SkChecksum::Compute(reinterpret_cast<uint32_t*>(fKey.begin()), keyLength);
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000359}
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000360
361GrGLProgramDesc& GrGLProgramDesc::operator= (const GrGLProgramDesc& other) {
bsalomon848faf02014-07-11 10:01:02 -0700362 size_t keyLength = other.keyLength();
363 fKey.reset(keyLength);
364 memcpy(fKey.begin(), other.fKey.begin(), keyLength);
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000365 return *this;
366}