blob: 8d0ea3d6b370f7df36ce9a6a90cf4eb21a2df00b [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"
11#include "GrDrawEffect.h"
12#include "GrEffect.h"
13#include "GrGpuGL.h"
14
bsalomon@google.com2db3ded2013-05-22 14:34:04 +000015#include "SkChecksum.h"
16
bsalomon929f29a2014-07-17 07:55:11 -070017bool GrGLProgramDesc::GetEffectKeyAndUpdateStats(const GrEffectStage& stage,
18 const GrGLCaps& caps,
19 bool useExplicitLocalCoords,
20 GrEffectKeyBuilder* b,
21 uint16_t* effectKeySize,
22 bool* setTrueIfReadsDst,
23 bool* setTrueIfReadsPos,
kkinnunenec56e452014-08-25 22:21:16 -070024 bool* setTrueIfRequiresVertexShader) {
bsalomon848faf02014-07-11 10:01:02 -070025 const GrBackendEffectFactory& factory = stage.getEffect()->getFactory();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000026 GrDrawEffect drawEffect(stage, useExplicitLocalCoords);
bsalomon848faf02014-07-11 10:01:02 -070027 if (stage.getEffect()->willReadDstColor()) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000028 *setTrueIfReadsDst = true;
29 }
bsalomon848faf02014-07-11 10:01:02 -070030 if (stage.getEffect()->willReadFragmentPosition()) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000031 *setTrueIfReadsPos = true;
32 }
kkinnunenec56e452014-08-25 22:21:16 -070033 if (stage.getEffect()->requiresVertexShader()) {
34 *setTrueIfRequiresVertexShader = true;
commit-bot@chromium.org234d4fb2013-09-30 19:55:49 +000035 }
bsalomon929f29a2014-07-17 07:55:11 -070036 factory.getGLEffectKey(drawEffect, caps, b);
37 size_t size = b->size();
38 if (size > SK_MaxU16) {
39 *effectKeySize = 0; // suppresses a warning.
40 return false;
41 }
42 *effectKeySize = SkToU16(size);
43 if (!GrGLProgramEffects::GenEffectMetaKey(drawEffect, caps, b)) {
44 return false;
45 }
46 return true;
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000047}
bsalomon848faf02014-07-11 10:01:02 -070048
49bool GrGLProgramDesc::Build(const GrDrawState& drawState,
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +000050 GrGpu::DrawType drawType,
bsalomon@google.com798c8c42013-03-27 19:50:27 +000051 GrDrawState::BlendOptFlags blendOpts,
52 GrBlendCoeff srcCoeff,
53 GrBlendCoeff dstCoeff,
54 const GrGpuGL* gpu,
bsalomon@google.com26e18b52013-03-29 19:22:36 +000055 const GrDeviceCoordTexture* dstCopy,
joshualittbd769d02014-09-04 08:56:46 -070056 const GrEffectStage** geometryProcessor,
bsalomon@google.com2c84aa32013-06-06 20:28:57 +000057 SkTArray<const GrEffectStage*, true>* colorStages,
58 SkTArray<const GrEffectStage*, true>* coverageStages,
bsalomon@google.com798c8c42013-03-27 19:50:27 +000059 GrGLProgramDesc* desc) {
bsalomon@google.com2c84aa32013-06-06 20:28:57 +000060 colorStages->reset();
61 coverageStages->reset();
62
bsalomon@google.com798c8c42013-03-27 19:50:27 +000063 // This should already have been caught
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000064 SkASSERT(!(GrDrawState::kSkipDraw_BlendOptFlag & blendOpts));
bsalomon@google.com798c8c42013-03-27 19:50:27 +000065
66 bool skipCoverage = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag);
67
68 bool skipColor = SkToBool(blendOpts & (GrDrawState::kEmitTransBlack_BlendOptFlag |
69 GrDrawState::kEmitCoverage_BlendOptFlag));
egdaniel02cafcc2014-07-21 11:37:28 -070070
commit-bot@chromium.orga34995e2013-10-23 05:42:03 +000071 int firstEffectiveColorStage = 0;
72 bool inputColorIsUsed = true;
joshualittbd769d02014-09-04 08:56:46 -070073
commit-bot@chromium.orga34995e2013-10-23 05:42:03 +000074 if (!skipColor) {
75 firstEffectiveColorStage = drawState.numColorStages();
76 while (firstEffectiveColorStage > 0 && inputColorIsUsed) {
77 --firstEffectiveColorStage;
bsalomonf99f8842014-07-07 11:54:23 -070078 const GrEffect* effect = drawState.getColorStage(firstEffectiveColorStage).getEffect();
commit-bot@chromium.orga34995e2013-10-23 05:42:03 +000079 inputColorIsUsed = effect->willUseInputColor();
80 }
81 }
82
83 int firstEffectiveCoverageStage = 0;
84 bool inputCoverageIsUsed = true;
85 if (!skipCoverage) {
86 firstEffectiveCoverageStage = drawState.numCoverageStages();
87 while (firstEffectiveCoverageStage > 0 && inputCoverageIsUsed) {
88 --firstEffectiveCoverageStage;
bsalomonf99f8842014-07-07 11:54:23 -070089 const GrEffect* effect = drawState.getCoverageStage(firstEffectiveCoverageStage).getEffect();
commit-bot@chromium.orga34995e2013-10-23 05:42:03 +000090 inputCoverageIsUsed = effect->willUseInputColor();
91 }
92 }
bsalomon@google.com798c8c42013-03-27 19:50:27 +000093
94 // The descriptor is used as a cache key. Thus when a field of the
95 // descriptor will not affect program generation (because of the attribute
96 // bindings in use or other descriptor field settings) it should be set
97 // to a canonical value to avoid duplicate programs with different keys.
98
jvanverth@google.com054ae992013-04-01 20:06:51 +000099 bool requiresColorAttrib = !skipColor && drawState.hasColorVertexAttribute();
100 bool requiresCoverageAttrib = !skipCoverage && drawState.hasCoverageVertexAttribute();
101 // we only need the local coords if we're actually going to generate effect code
102 bool requiresLocalCoordAttrib = !(skipCoverage && skipColor) &&
103 drawState.hasLocalCoordAttribute();
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000104
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000105 bool readsDst = false;
bsalomon@google.comb5158812013-05-13 18:50:25 +0000106 bool readFragPosition = false;
kkinnunenec56e452014-08-25 22:21:16 -0700107
108 // Provide option for shader programs without vertex shader only when drawing paths.
109 bool requiresVertexShader = !GrGpu::IsPathRenderingDrawType(drawType);
110
bsalomon848faf02014-07-11 10:01:02 -0700111 int numStages = 0;
joshualittbd769d02014-09-04 08:56:46 -0700112 if (drawState.hasGeometryProcessor()) {
113 numStages++;
114 }
bsalomon848faf02014-07-11 10:01:02 -0700115 if (!skipColor) {
116 numStages += drawState.numColorStages() - firstEffectiveColorStage;
117 }
118 if (!skipCoverage) {
119 numStages += drawState.numCoverageStages() - firstEffectiveCoverageStage;
120 }
bsalomon929f29a2014-07-17 07:55:11 -0700121 GR_STATIC_ASSERT(0 == kEffectKeyOffsetsAndLengthOffset % sizeof(uint32_t));
bsalomon848faf02014-07-11 10:01:02 -0700122 // Make room for everything up to and including the array of offsets to effect keys.
123 desc->fKey.reset();
bsalomon929f29a2014-07-17 07:55:11 -0700124 desc->fKey.push_back_n(kEffectKeyOffsetsAndLengthOffset + 2 * sizeof(uint16_t) * numStages);
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000125
bsalomon929f29a2014-07-17 07:55:11 -0700126 int offsetAndSizeIndex = 0;
bsalomon848faf02014-07-11 10:01:02 -0700127 bool effectKeySuccess = true;
joshualittbd769d02014-09-04 08:56:46 -0700128
129 KeyHeader* header = desc->header();
130 // make sure any padding in the header is zeroed.
131 memset(desc->header(), 0, kHeaderSize);
132
133 // We can only have one effect which touches the vertex shader
134 if (drawState.hasGeometryProcessor()) {
135 uint16_t* offsetAndSize =
bsalomon929f29a2014-07-17 07:55:11 -0700136 reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
137 offsetAndSizeIndex * 2 * sizeof(uint16_t));
bsalomon848faf02014-07-11 10:01:02 -0700138
139 GrEffectKeyBuilder b(&desc->fKey);
bsalomon929f29a2014-07-17 07:55:11 -0700140 uint16_t effectKeySize;
141 uint32_t effectOffset = desc->fKey.count();
142 effectKeySuccess |= GetEffectKeyAndUpdateStats(
joshualittbd769d02014-09-04 08:56:46 -0700143 *drawState.getGeometryProcessor(), gpu->glCaps(),
bsalomon929f29a2014-07-17 07:55:11 -0700144 requiresLocalCoordAttrib, &b,
145 &effectKeySize, &readsDst,
kkinnunenec56e452014-08-25 22:21:16 -0700146 &readFragPosition, &requiresVertexShader);
bsalomon929f29a2014-07-17 07:55:11 -0700147 effectKeySuccess |= (effectOffset <= SK_MaxU16);
148
149 offsetAndSize[0] = SkToU16(effectOffset);
150 offsetAndSize[1] = effectKeySize;
151 ++offsetAndSizeIndex;
joshualittbd769d02014-09-04 08:56:46 -0700152 *geometryProcessor = drawState.getGeometryProcessor();
153 SkASSERT(requiresVertexShader);
154 header->fHasGeometryProcessor = true;
155 }
156
157 if (!skipColor) {
158 for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
159 uint16_t* offsetAndSize =
160 reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
161 offsetAndSizeIndex * 2 * sizeof(uint16_t));
162
163 bool effectRequiresVertexShader = false;
164 GrEffectKeyBuilder b(&desc->fKey);
165 uint16_t effectKeySize;
166 uint32_t effectOffset = desc->fKey.count();
167 effectKeySuccess |= GetEffectKeyAndUpdateStats(
168 drawState.getColorStage(s), gpu->glCaps(),
169 requiresLocalCoordAttrib, &b,
170 &effectKeySize, &readsDst,
171 &readFragPosition, &effectRequiresVertexShader);
172 effectKeySuccess |= (effectOffset <= SK_MaxU16);
173
174 offsetAndSize[0] = SkToU16(effectOffset);
175 offsetAndSize[1] = effectKeySize;
176 ++offsetAndSizeIndex;
177 SkASSERT(!effectRequiresVertexShader);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000178 }
179 }
180 if (!skipCoverage) {
commit-bot@chromium.orga34995e2013-10-23 05:42:03 +0000181 for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) {
bsalomon929f29a2014-07-17 07:55:11 -0700182 uint16_t* offsetAndSize =
183 reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
184 offsetAndSizeIndex * 2 * sizeof(uint16_t));
185
joshualittbd769d02014-09-04 08:56:46 -0700186 bool effectRequiresVertexShader = false;
bsalomon848faf02014-07-11 10:01:02 -0700187 GrEffectKeyBuilder b(&desc->fKey);
bsalomon929f29a2014-07-17 07:55:11 -0700188 uint16_t effectKeySize;
189 uint32_t effectOffset = desc->fKey.count();
190 effectKeySuccess |= GetEffectKeyAndUpdateStats(
191 drawState.getCoverageStage(s), gpu->glCaps(),
192 requiresLocalCoordAttrib, &b,
193 &effectKeySize, &readsDst,
joshualittbd769d02014-09-04 08:56:46 -0700194 &readFragPosition, &effectRequiresVertexShader);
bsalomon929f29a2014-07-17 07:55:11 -0700195 effectKeySuccess |= (effectOffset <= SK_MaxU16);
196
197 offsetAndSize[0] = SkToU16(effectOffset);
198 offsetAndSize[1] = effectKeySize;
199 ++offsetAndSizeIndex;
joshualittbd769d02014-09-04 08:56:46 -0700200 SkASSERT(!effectRequiresVertexShader);
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000201 }
202 }
bsalomon848faf02014-07-11 10:01:02 -0700203 if (!effectKeySuccess) {
204 desc->fKey.reset();
205 return false;
206 }
207
bsalomon848faf02014-07-11 10:01:02 -0700208 // Because header is a pointer into the dynamic array, we can't push any new data into the key
209 // below here.
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000210
kkinnunenec56e452014-08-25 22:21:16 -0700211 header->fRequiresVertexShader = requiresVertexShader || requiresLocalCoordAttrib;
commit-bot@chromium.org0a6fe712014-04-23 19:26:26 +0000212 header->fEmitsPointSize = GrGpu::kDrawPoints_DrawType == drawType;
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000213
214 // Currently the experimental GS will only work with triangle prims (and it doesn't do anything
215 // other than pass through values from the VS to the FS anyway).
216#if GR_GL_EXPERIMENTAL_GS
217#if 0
218 header->fExperimentalGS = gpu->caps().geometryShaderSupport();
219#else
220 header->fExperimentalGS = false;
221#endif
222#endif
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000223 bool defaultToUniformInputs = GR_GL_NO_CONSTANT_ATTRIBUTES || gpu->caps()->pathRenderingSupport();
224
egdaniel842b0862014-09-02 10:01:30 -0700225 if (!inputColorIsUsed && !skipColor) {
226 header->fColorInput = kAllOnes_ColorInput;
227 } else if (defaultToUniformInputs && !requiresColorAttrib && inputColorIsUsed) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000228 header->fColorInput = kUniform_ColorInput;
229 } else {
230 header->fColorInput = kAttribute_ColorInput;
kkinnunenec56e452014-08-25 22:21:16 -0700231 header->fRequiresVertexShader = true;
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000232 }
233
commit-bot@chromium.orge0a868c2013-11-22 07:02:11 +0000234 bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverageColor();
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000235
egdaniel02cafcc2014-07-21 11:37:28 -0700236 if ((covIsSolidWhite || !inputCoverageIsUsed) && !skipCoverage) {
egdaniel842b0862014-09-02 10:01:30 -0700237 header->fCoverageInput = kAllOnes_ColorInput;
egdaniel02cafcc2014-07-21 11:37:28 -0700238 } else if (defaultToUniformInputs && !requiresCoverageAttrib && inputCoverageIsUsed) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000239 header->fCoverageInput = kUniform_ColorInput;
240 } else {
241 header->fCoverageInput = kAttribute_ColorInput;
kkinnunenec56e452014-08-25 22:21:16 -0700242 header->fRequiresVertexShader = true;
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000243 }
244
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000245 if (readsDst) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000246 SkASSERT(NULL != dstCopy || gpu->caps()->dstReadInShaderSupport());
bsalomon@google.com6b0cf022013-05-03 13:35:14 +0000247 const GrTexture* dstCopyTexture = NULL;
248 if (NULL != dstCopy) {
249 dstCopyTexture = dstCopy->texture();
250 }
joshualitt30ba4362014-08-21 20:18:45 -0700251 header->fDstReadKey = GrGLFragmentShaderBuilder::KeyForDstRead(dstCopyTexture,
252 gpu->glCaps());
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000253 SkASSERT(0 != header->fDstReadKey);
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000254 } else {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000255 header->fDstReadKey = 0;
bsalomon@google.comb5158812013-05-13 18:50:25 +0000256 }
257
258 if (readFragPosition) {
joshualitt30ba4362014-08-21 20:18:45 -0700259 header->fFragPosKey = GrGLFragmentShaderBuilder::KeyForFragmentPosition(
260 drawState.getRenderTarget(), gpu->glCaps());
bsalomon@google.comb5158812013-05-13 18:50:25 +0000261 } else {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000262 header->fFragPosKey = 0;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000263 }
264
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000265 // Record attribute indices
266 header->fPositionAttributeIndex = drawState.positionAttributeIndex();
267 header->fLocalCoordAttributeIndex = drawState.localCoordAttributeIndex();
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +0000268
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000269 // For constant color and coverage we need an attribute with an index beyond those already set
270 int availableAttributeIndex = drawState.getVertexAttribCount();
271 if (requiresColorAttrib) {
272 header->fColorAttributeIndex = drawState.colorVertexAttributeIndex();
273 } else if (GrGLProgramDesc::kAttribute_ColorInput == header->fColorInput) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000274 SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000275 header->fColorAttributeIndex = availableAttributeIndex;
276 availableAttributeIndex++;
277 } else {
278 header->fColorAttributeIndex = -1;
279 }
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +0000280
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000281 if (requiresCoverageAttrib) {
282 header->fCoverageAttributeIndex = drawState.coverageVertexAttributeIndex();
283 } else if (GrGLProgramDesc::kAttribute_ColorInput == header->fCoverageInput) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000284 SkASSERT(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000285 header->fCoverageAttributeIndex = availableAttributeIndex;
286 } else {
287 header->fCoverageAttributeIndex = -1;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000288 }
289
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000290 // Here we deal with whether/how we handle color and coverage separately.
skia.committer@gmail.com2d816ad2013-05-23 07:01:22 +0000291
commit-bot@chromium.org8a135882014-02-05 16:29:12 +0000292 // Set this default and then possibly change our mind if there is coverage.
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000293 header->fCoverageOutput = kModulate_CoverageOutput;
294
295 // If we do have coverage determine whether it matters.
joshualittbd769d02014-09-04 08:56:46 -0700296 bool separateCoverageFromColor = drawState.hasGeometryProcessor();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000297 if (!drawState.isCoverageDrawing() && !skipCoverage &&
joshualittbd769d02014-09-04 08:56:46 -0700298 (drawState.numCoverageStages() > 0 ||
299 drawState.hasGeometryProcessor() ||
300 requiresCoverageAttrib)) {
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000301
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000302 if (gpu->caps()->dualSourceBlendingSupport() &&
303 !(blendOpts & (GrDrawState::kEmitCoverage_BlendOptFlag |
304 GrDrawState::kCoverageAsAlpha_BlendOptFlag))) {
305 if (kZero_GrBlendCoeff == dstCoeff) {
306 // write the coverage value to second color
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000307 header->fCoverageOutput = kSecondaryCoverage_CoverageOutput;
308 separateCoverageFromColor = true;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000309 } else if (kSA_GrBlendCoeff == dstCoeff) {
310 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000311 header->fCoverageOutput = kSecondaryCoverageISA_CoverageOutput;
312 separateCoverageFromColor = true;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000313 } else if (kSC_GrBlendCoeff == dstCoeff) {
314 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000315 header->fCoverageOutput = kSecondaryCoverageISC_CoverageOutput;
316 separateCoverageFromColor = true;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000317 }
bsalomon@google.com5920ac22013-04-19 13:14:45 +0000318 } else if (readsDst &&
bsalomon@google.com0c89db22013-05-15 17:53:04 +0000319 kOne_GrBlendCoeff == srcCoeff &&
320 kZero_GrBlendCoeff == dstCoeff) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000321 header->fCoverageOutput = kCombineWithDst_CoverageOutput;
322 separateCoverageFromColor = true;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000323 }
324 }
joshualittbd769d02014-09-04 08:56:46 -0700325
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000326 if (!skipColor) {
commit-bot@chromium.orga34995e2013-10-23 05:42:03 +0000327 for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000328 colorStages->push_back(&drawState.getColorStage(s));
329 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000330 }
331 if (!skipCoverage) {
332 SkTArray<const GrEffectStage*, true>* array;
333 if (separateCoverageFromColor) {
334 array = coverageStages;
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000335 } else {
336 array = colorStages;
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000337 }
commit-bot@chromium.orga34995e2013-10-23 05:42:03 +0000338 for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000339 array->push_back(&drawState.getCoverageStage(s));
340 }
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000341 }
commit-bot@chromium.orga34995e2013-10-23 05:42:03 +0000342 header->fColorEffectCnt = colorStages->count();
343 header->fCoverageEffectCnt = coverageStages->count();
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000344
bsalomon848faf02014-07-11 10:01:02 -0700345 desc->finalize();
346 return true;
347}
348
349void GrGLProgramDesc::finalize() {
350 int keyLength = fKey.count();
351 SkASSERT(0 == (keyLength % 4));
352 *this->atOffset<uint32_t, kLengthOffset>() = SkToU32(keyLength);
353
354 uint32_t* checksum = this->atOffset<uint32_t, kChecksumOffset>();
355 *checksum = 0;
356 *checksum = SkChecksum::Compute(reinterpret_cast<uint32_t*>(fKey.begin()), keyLength);
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000357}
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000358
359GrGLProgramDesc& GrGLProgramDesc::operator= (const GrGLProgramDesc& other) {
bsalomon848faf02014-07-11 10:01:02 -0700360 size_t keyLength = other.keyLength();
361 fKey.reset(keyLength);
362 memcpy(fKey.begin(), other.fKey.begin(), keyLength);
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000363 return *this;
364}