1 /*
2 * Copyright 2011 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
8 #include "GrGpuGL.h"
9
10 #include "GrEffect.h"
11 #include "GrGLEffect.h"
12 #include "GrGpuVertex.h"
13
14 typedef GrGLUniformManager::UniformHandle UniformHandle;
15 static const UniformHandle kInvalidUniformHandle = GrGLUniformManager::kInvalidUniformHandle;
16
17 #define SKIP_CACHE_CHECK true
18 #define GR_UINT32_MAX static_cast<uint32_t>(-1)
19
ProgramCache(const GrGLContextInfo & gl)20 GrGpuGL::ProgramCache::ProgramCache(const GrGLContextInfo& gl)
21 : fCount(0)
22 , fCurrLRUStamp(0)
23 , fGL(gl) {
24 }
25
abandon()26 void GrGpuGL::ProgramCache::abandon() {
27 for (int i = 0; i < fCount; ++i) {
28 GrAssert(NULL != fEntries[i].fProgram.get());
29 fEntries[i].fProgram->abandon();
30 fEntries[i].fProgram.reset(NULL);
31 }
32 fCount = 0;
33 }
34
getProgram(const ProgramDesc & desc,const GrEffectStage * stages[])35 GrGLProgram* GrGpuGL::ProgramCache::getProgram(const ProgramDesc& desc,
36 const GrEffectStage* stages[]) {
37 Entry newEntry;
38 newEntry.fKey.setKeyData(desc.asKey());
39
40 Entry* entry = fHashCache.find(newEntry.fKey);
41 if (NULL == entry) {
42 newEntry.fProgram.reset(GrGLProgram::Create(fGL, desc, stages));
43 if (NULL == newEntry.fProgram.get()) {
44 return NULL;
45 }
46 if (fCount < kMaxEntries) {
47 entry = fEntries + fCount;
48 ++fCount;
49 } else {
50 GrAssert(kMaxEntries == fCount);
51 entry = fEntries;
52 for (int i = 1; i < kMaxEntries; ++i) {
53 if (fEntries[i].fLRUStamp < entry->fLRUStamp) {
54 entry = fEntries + i;
55 }
56 }
57 fHashCache.remove(entry->fKey, entry);
58 }
59 *entry = newEntry;
60 fHashCache.insert(entry->fKey, entry);
61 }
62
63 entry->fLRUStamp = fCurrLRUStamp;
64 if (GR_UINT32_MAX == fCurrLRUStamp) {
65 // wrap around! just trash our LRU, one time hit.
66 for (int i = 0; i < fCount; ++i) {
67 fEntries[i].fLRUStamp = 0;
68 }
69 }
70 ++fCurrLRUStamp;
71 return entry->fProgram;
72 }
73
74 ////////////////////////////////////////////////////////////////////////////////
75
abandonResources()76 void GrGpuGL::abandonResources(){
77 INHERITED::abandonResources();
78 fProgramCache->abandon();
79 fHWProgramID = 0;
80 }
81
82 ////////////////////////////////////////////////////////////////////////////////
83
84 #define GL_CALL(X) GR_GL_CALL(this->glInterface(), X)
85
flushViewMatrix(DrawType type)86 void GrGpuGL::flushViewMatrix(DrawType type) {
87 const GrGLRenderTarget* rt = static_cast<const GrGLRenderTarget*>(this->getDrawState().getRenderTarget());
88 SkISize viewportSize;
89 const GrGLIRect& viewport = rt->getViewport();
90 viewportSize.set(viewport.fWidth, viewport.fHeight);
91
92 const SkMatrix& vm = this->getDrawState().getViewMatrix();
93
94 if (kStencilPath_DrawType == type) {
95 if (fHWPathMatrixState.fViewMatrix != vm ||
96 fHWPathMatrixState.fRTSize != viewportSize) {
97 // rescale the coords from skia's "device" coords to GL's normalized coords,
98 // and perform a y-flip.
99 SkMatrix m;
100 m.setScale(SkIntToScalar(2) / rt->width(), SkIntToScalar(-2) / rt->height());
101 m.postTranslate(-SK_Scalar1, SK_Scalar1);
102 m.preConcat(vm);
103
104 // GL wants a column-major 4x4.
105 GrGLfloat mv[] = {
106 // col 0
107 SkScalarToFloat(m[SkMatrix::kMScaleX]),
108 SkScalarToFloat(m[SkMatrix::kMSkewY]),
109 0,
110 SkScalarToFloat(m[SkMatrix::kMPersp0]),
111
112 // col 1
113 SkScalarToFloat(m[SkMatrix::kMSkewX]),
114 SkScalarToFloat(m[SkMatrix::kMScaleY]),
115 0,
116 SkScalarToFloat(m[SkMatrix::kMPersp1]),
117
118 // col 2
119 0, 0, 0, 0,
120
121 // col3
122 SkScalarToFloat(m[SkMatrix::kMTransX]),
123 SkScalarToFloat(m[SkMatrix::kMTransY]),
124 0.0f,
125 SkScalarToFloat(m[SkMatrix::kMPersp2])
126 };
127 GL_CALL(MatrixMode(GR_GL_PROJECTION));
128 GL_CALL(LoadMatrixf(mv));
129 fHWPathMatrixState.fViewMatrix = vm;
130 fHWPathMatrixState.fRTSize = viewportSize;
131 }
132 } else if (!fCurrentProgram->fViewMatrix.cheapEqualTo(vm) ||
133 fCurrentProgram->fViewportSize != viewportSize) {
134 SkMatrix m;
135 m.setAll(
136 SkIntToScalar(2) / viewportSize.fWidth, 0, -SK_Scalar1,
137 0,-SkIntToScalar(2) / viewportSize.fHeight, SK_Scalar1,
138 0, 0, SkMatrix::I()[8]);
139 m.setConcat(m, vm);
140
141 // ES doesn't allow you to pass true to the transpose param,
142 // so do our own transpose
143 GrGLfloat mt[] = {
144 SkScalarToFloat(m[SkMatrix::kMScaleX]),
145 SkScalarToFloat(m[SkMatrix::kMSkewY]),
146 SkScalarToFloat(m[SkMatrix::kMPersp0]),
147 SkScalarToFloat(m[SkMatrix::kMSkewX]),
148 SkScalarToFloat(m[SkMatrix::kMScaleY]),
149 SkScalarToFloat(m[SkMatrix::kMPersp1]),
150 SkScalarToFloat(m[SkMatrix::kMTransX]),
151 SkScalarToFloat(m[SkMatrix::kMTransY]),
152 SkScalarToFloat(m[SkMatrix::kMPersp2])
153 };
154 fCurrentProgram->fUniformManager.setMatrix3f(
155 fCurrentProgram->fUniformHandles.fViewMatrixUni,
156 mt);
157 fCurrentProgram->fViewMatrix = vm;
158 fCurrentProgram->fViewportSize = viewportSize;
159 }
160 }
161
162 ///////////////////////////////////////////////////////////////////////////////
163
flushColor(GrColor color)164 void GrGpuGL::flushColor(GrColor color) {
165 const ProgramDesc& desc = fCurrentProgram->getDesc();
166 const GrDrawState& drawState = this->getDrawState();
167
168 if (this->getVertexLayout() & GrDrawState::kColor_VertexLayoutBit) {
169 // color will be specified per-vertex as an attribute
170 // invalidate the const vertex attrib color
171 fHWConstAttribColor = GrColor_ILLEGAL;
172 } else {
173 switch (desc.fColorInput) {
174 case ProgramDesc::kAttribute_ColorInput:
175 if (fHWConstAttribColor != color) {
176 // OpenGL ES only supports the float varieties of glVertexAttrib
177 GrGLfloat c[4];
178 GrColorToRGBAFloat(color, c);
179 GL_CALL(VertexAttrib4fv(GrGLProgram::ColorAttributeIdx(), c));
180 fHWConstAttribColor = color;
181 }
182 break;
183 case ProgramDesc::kUniform_ColorInput:
184 if (fCurrentProgram->fColor != color) {
185 // OpenGL ES doesn't support unsigned byte varieties of glUniform
186 GrGLfloat c[4];
187 GrColorToRGBAFloat(color, c);
188 GrAssert(kInvalidUniformHandle != fCurrentProgram->fUniformHandles.fColorUni);
189 fCurrentProgram->fUniformManager.set4fv(
190 fCurrentProgram->fUniformHandles.fColorUni,
191 0, 1, c);
192 fCurrentProgram->fColor = color;
193 }
194 break;
195 case ProgramDesc::kSolidWhite_ColorInput:
196 case ProgramDesc::kTransBlack_ColorInput:
197 break;
198 default:
199 GrCrash("Unknown color type.");
200 }
201 }
202 UniformHandle filterColorUni = fCurrentProgram->fUniformHandles.fColorFilterUni;
203 if (kInvalidUniformHandle != filterColorUni &&
204 fCurrentProgram->fColorFilterColor != drawState.getColorFilterColor()) {
205 GrGLfloat c[4];
206 GrColorToRGBAFloat(drawState.getColorFilterColor(), c);
207 fCurrentProgram->fUniformManager.set4fv(filterColorUni, 0, 1, c);
208 fCurrentProgram->fColorFilterColor = drawState.getColorFilterColor();
209 }
210 }
211
flushCoverage(GrColor coverage)212 void GrGpuGL::flushCoverage(GrColor coverage) {
213 const ProgramDesc& desc = fCurrentProgram->getDesc();
214 // const GrDrawState& drawState = this->getDrawState();
215
216
217 if (this->getVertexLayout() & GrDrawState::kCoverage_VertexLayoutBit) {
218 // coverage will be specified per-vertex as an attribute
219 // invalidate the const vertex attrib coverage
220 fHWConstAttribCoverage = GrColor_ILLEGAL;
221 } else {
222 switch (desc.fCoverageInput) {
223 case ProgramDesc::kAttribute_ColorInput:
224 if (fHWConstAttribCoverage != coverage) {
225 // OpenGL ES only supports the float varieties of
226 // glVertexAttrib
227 GrGLfloat c[4];
228 GrColorToRGBAFloat(coverage, c);
229 GL_CALL(VertexAttrib4fv(GrGLProgram::CoverageAttributeIdx(),
230 c));
231 fHWConstAttribCoverage = coverage;
232 }
233 break;
234 case ProgramDesc::kUniform_ColorInput:
235 if (fCurrentProgram->fCoverage != coverage) {
236 // OpenGL ES doesn't support unsigned byte varieties of
237 // glUniform
238 GrGLfloat c[4];
239 GrColorToRGBAFloat(coverage, c);
240 GrAssert(kInvalidUniformHandle !=
241 fCurrentProgram->fUniformHandles.fCoverageUni);
242 fCurrentProgram->fUniformManager.set4fv(
243 fCurrentProgram->fUniformHandles.fCoverageUni,
244 0, 1, c);
245 fCurrentProgram->fCoverage = coverage;
246 }
247 break;
248 case ProgramDesc::kSolidWhite_ColorInput:
249 case ProgramDesc::kTransBlack_ColorInput:
250 break;
251 default:
252 GrCrash("Unknown coverage type.");
253 }
254 }
255 }
256
flushGraphicsState(DrawType type)257 bool GrGpuGL::flushGraphicsState(DrawType type) {
258 const GrDrawState& drawState = this->getDrawState();
259
260 // GrGpu::setupClipAndFlushState should have already checked this
261 // and bailed if not true.
262 GrAssert(NULL != drawState.getRenderTarget());
263
264 if (kStencilPath_DrawType != type) {
265 this->flushMiscFixedFunctionState();
266
267 GrBlendCoeff srcCoeff;
268 GrBlendCoeff dstCoeff;
269 BlendOptFlags blendOpts = this->getBlendOpts(false, &srcCoeff, &dstCoeff);
270 if (kSkipDraw_BlendOptFlag & blendOpts) {
271 return false;
272 }
273
274 const GrEffectStage* stages[GrDrawState::kNumStages];
275 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
276 stages[i] = drawState.isStageEnabled(i) ? &drawState.getStage(i) : NULL;
277 }
278 GrGLProgram::Desc desc;
279 this->buildProgram(kDrawPoints_DrawType == type, blendOpts, dstCoeff, &desc);
280
281 fCurrentProgram.reset(fProgramCache->getProgram(desc, stages));
282 if (NULL == fCurrentProgram.get()) {
283 GrAssert(!"Failed to create program!");
284 return false;
285 }
286 fCurrentProgram.get()->ref();
287
288 if (fHWProgramID != fCurrentProgram->fProgramID) {
289 GL_CALL(UseProgram(fCurrentProgram->fProgramID));
290 fHWProgramID = fCurrentProgram->fProgramID;
291 }
292 fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff);
293 this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff);
294
295 GrColor color;
296 GrColor coverage;
297 if (blendOpts & kEmitTransBlack_BlendOptFlag) {
298 color = 0;
299 coverage = 0;
300 } else if (blendOpts & kEmitCoverage_BlendOptFlag) {
301 color = 0xffffffff;
302 coverage = drawState.getCoverage();
303 } else {
304 color = drawState.getColor();
305 coverage = drawState.getCoverage();
306 }
307 this->flushColor(color);
308 this->flushCoverage(coverage);
309
310 fCurrentProgram->setData(this);
311 }
312 this->flushStencil(type);
313 this->flushViewMatrix(type);
314 this->flushScissor();
315 this->flushAAState(type);
316
317 GrIRect* devRect = NULL;
318 GrIRect devClipBounds;
319 if (drawState.isClipState()) {
320 this->getClip()->getConservativeBounds(drawState.getRenderTarget(), &devClipBounds);
321 devRect = &devClipBounds;
322 }
323 // This must come after textures are flushed because a texture may need
324 // to be msaa-resolved (which will modify bound FBO state).
325 this->flushRenderTarget(devRect);
326
327 return true;
328 }
329
330 #if GR_TEXT_SCALAR_IS_USHORT
331 #define TEXT_COORDS_GL_TYPE GR_GL_UNSIGNED_SHORT
332 #define TEXT_COORDS_ARE_NORMALIZED 1
333 #elif GR_TEXT_SCALAR_IS_FLOAT
334 #define TEXT_COORDS_GL_TYPE GR_GL_FLOAT
335 #define TEXT_COORDS_ARE_NORMALIZED 0
336 #elif GR_TEXT_SCALAR_IS_FIXED
337 #define TEXT_COORDS_GL_TYPE GR_GL_FIXED
338 #define TEXT_COORDS_ARE_NORMALIZED 0
339 #else
340 #error "unknown GR_TEXT_SCALAR type"
341 #endif
342
setupGeometry(const DrawInfo & info,int * startIndexOffset)343 void GrGpuGL::setupGeometry(const DrawInfo& info, int* startIndexOffset) {
344
345 int newColorOffset;
346 int newCoverageOffset;
347 int newTexCoordOffsets[GrDrawState::kMaxTexCoords];
348 int newEdgeOffset;
349
350 GrVertexLayout currLayout = this->getVertexLayout();
351
352 GrGLsizei newStride = GrDrawState::VertexSizeAndOffsetsByIdx(currLayout,
353 newTexCoordOffsets,
354 &newColorOffset,
355 &newCoverageOffset,
356 &newEdgeOffset);
357 int oldColorOffset;
358 int oldCoverageOffset;
359 int oldTexCoordOffsets[GrDrawState::kMaxTexCoords];
360 int oldEdgeOffset;
361
362 GrGLsizei oldStride = GrDrawState::VertexSizeAndOffsetsByIdx(fHWGeometryState.fVertexLayout,
363 oldTexCoordOffsets,
364 &oldColorOffset,
365 &oldCoverageOffset,
366 &oldEdgeOffset);
367
368 int extraVertexOffset;
369 this->setBuffers(info.isIndexed(), &extraVertexOffset, startIndexOffset);
370
371 GrGLenum scalarType;
372 bool texCoordNorm;
373 if (currLayout & GrDrawState::kTextFormat_VertexLayoutBit) {
374 scalarType = TEXT_COORDS_GL_TYPE;
375 texCoordNorm = SkToBool(TEXT_COORDS_ARE_NORMALIZED);
376 } else {
377 scalarType = GR_GL_FLOAT;
378 texCoordNorm = false;
379 }
380
381 size_t vertexOffset = (info.startVertex() + extraVertexOffset) * newStride;
382
383 // all the Pointers must be set if any of these are true
384 bool allOffsetsChange = fHWGeometryState.fArrayPtrsDirty ||
385 vertexOffset != fHWGeometryState.fVertexOffset ||
386 newStride != oldStride;
387
388 // position and tex coord offsets change if above conditions are true
389 // or the type/normalization changed based on text vs nontext type coords.
390 bool posAndTexChange = allOffsetsChange ||
391 (((TEXT_COORDS_GL_TYPE != GR_GL_FLOAT) || TEXT_COORDS_ARE_NORMALIZED) &&
392 (GrDrawState::kTextFormat_VertexLayoutBit &
393 (fHWGeometryState.fVertexLayout ^ currLayout)));
394
395 if (posAndTexChange) {
396 int idx = GrGLProgram::PositionAttributeIdx();
397 GL_CALL(VertexAttribPointer(idx, 2, scalarType, false, newStride,
398 (GrGLvoid*)vertexOffset));
399 fHWGeometryState.fVertexOffset = vertexOffset;
400 }
401
402 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
403 if (newTexCoordOffsets[t] > 0) {
404 GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffsets[t]);
405 int idx = GrGLProgram::TexCoordAttributeIdx(t);
406 if (oldTexCoordOffsets[t] <= 0) {
407 GL_CALL(EnableVertexAttribArray(idx));
408 GL_CALL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm,
409 newStride, texCoordOffset));
410 } else if (posAndTexChange ||
411 newTexCoordOffsets[t] != oldTexCoordOffsets[t]) {
412 GL_CALL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm,
413 newStride, texCoordOffset));
414 }
415 } else if (oldTexCoordOffsets[t] > 0) {
416 GL_CALL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx(t)));
417 }
418 }
419
420 if (newColorOffset > 0) {
421 GrGLvoid* colorOffset = (int8_t*)(vertexOffset + newColorOffset);
422 int idx = GrGLProgram::ColorAttributeIdx();
423 if (oldColorOffset <= 0) {
424 GL_CALL(EnableVertexAttribArray(idx));
425 GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
426 true, newStride, colorOffset));
427 } else if (allOffsetsChange || newColorOffset != oldColorOffset) {
428 GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
429 true, newStride, colorOffset));
430 }
431 } else if (oldColorOffset > 0) {
432 GL_CALL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx()));
433 }
434
435 if (newCoverageOffset > 0) {
436 GrGLvoid* coverageOffset = (int8_t*)(vertexOffset + newCoverageOffset);
437 int idx = GrGLProgram::CoverageAttributeIdx();
438 if (oldCoverageOffset <= 0) {
439 GL_CALL(EnableVertexAttribArray(idx));
440 GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
441 true, newStride, coverageOffset));
442 } else if (allOffsetsChange || newCoverageOffset != oldCoverageOffset) {
443 GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
444 true, newStride, coverageOffset));
445 }
446 } else if (oldCoverageOffset > 0) {
447 GL_CALL(DisableVertexAttribArray(GrGLProgram::CoverageAttributeIdx()));
448 }
449
450 if (newEdgeOffset > 0) {
451 GrGLvoid* edgeOffset = (int8_t*)(vertexOffset + newEdgeOffset);
452 int idx = GrGLProgram::EdgeAttributeIdx();
453 if (oldEdgeOffset <= 0) {
454 GL_CALL(EnableVertexAttribArray(idx));
455 GL_CALL(VertexAttribPointer(idx, 4, scalarType,
456 false, newStride, edgeOffset));
457 } else if (allOffsetsChange || newEdgeOffset != oldEdgeOffset) {
458 GL_CALL(VertexAttribPointer(idx, 4, scalarType,
459 false, newStride, edgeOffset));
460 }
461 } else if (oldEdgeOffset > 0) {
462 GL_CALL(DisableVertexAttribArray(GrGLProgram::EdgeAttributeIdx()));
463 }
464
465 fHWGeometryState.fVertexLayout = currLayout;
466 fHWGeometryState.fArrayPtrsDirty = false;
467 }
468
buildProgram(bool isPoints,BlendOptFlags blendOpts,GrBlendCoeff dstCoeff,ProgramDesc * desc)469 void GrGpuGL::buildProgram(bool isPoints,
470 BlendOptFlags blendOpts,
471 GrBlendCoeff dstCoeff,
472 ProgramDesc* desc) {
473 const GrDrawState& drawState = this->getDrawState();
474
475 // This should already have been caught
476 GrAssert(!(kSkipDraw_BlendOptFlag & blendOpts));
477
478 bool skipCoverage = SkToBool(blendOpts & kEmitTransBlack_BlendOptFlag);
479
480 bool skipColor = SkToBool(blendOpts & (kEmitTransBlack_BlendOptFlag |
481 kEmitCoverage_BlendOptFlag));
482
483 // The descriptor is used as a cache key. Thus when a field of the
484 // descriptor will not affect program generation (because of the vertex
485 // layout in use or other descriptor field settings) it should be set
486 // to a canonical value to avoid duplicate programs with different keys.
487
488 // Must initialize all fields or cache will have false negatives!
489 desc->fVertexLayout = this->getVertexLayout();
490
491 desc->fEmitsPointSize = isPoints;
492
493 bool requiresAttributeColors = !skipColor &&
494 SkToBool(desc->fVertexLayout & GrDrawState::kColor_VertexLayoutBit);
495 bool requiresAttributeCoverage = !skipCoverage &&
496 SkToBool(desc->fVertexLayout & GrDrawState::kCoverage_VertexLayoutBit);
497
498 // fColorInput/fCoverageInput records how colors are specified for the.
499 // program. So we strip the bits from the layout to avoid false negatives
500 // when searching for an existing program in the cache.
501 desc->fVertexLayout &= ~(GrDrawState::kColor_VertexLayoutBit | GrDrawState::kCoverage_VertexLayoutBit);
502
503 desc->fColorFilterXfermode = skipColor ?
504 SkXfermode::kDst_Mode :
505 drawState.getColorFilterMode();
506
507 // no reason to do edge aa or look at per-vertex coverage if coverage is
508 // ignored
509 if (skipCoverage) {
510 desc->fVertexLayout &= ~(GrDrawState::kEdge_VertexLayoutBit | GrDrawState::kCoverage_VertexLayoutBit);
511 }
512
513 bool colorIsTransBlack = SkToBool(blendOpts & kEmitTransBlack_BlendOptFlag);
514 bool colorIsSolidWhite = (blendOpts & kEmitCoverage_BlendOptFlag) ||
515 (!requiresAttributeColors && 0xffffffff == drawState.getColor());
516 if (GR_AGGRESSIVE_SHADER_OPTS && colorIsTransBlack) {
517 desc->fColorInput = ProgramDesc::kTransBlack_ColorInput;
518 } else if (GR_AGGRESSIVE_SHADER_OPTS && colorIsSolidWhite) {
519 desc->fColorInput = ProgramDesc::kSolidWhite_ColorInput;
520 } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeColors) {
521 desc->fColorInput = ProgramDesc::kUniform_ColorInput;
522 } else {
523 desc->fColorInput = ProgramDesc::kAttribute_ColorInput;
524 }
525
526 bool covIsSolidWhite = !requiresAttributeCoverage && 0xffffffff == drawState.getCoverage();
527
528 if (skipCoverage) {
529 desc->fCoverageInput = ProgramDesc::kTransBlack_ColorInput;
530 } else if (covIsSolidWhite) {
531 desc->fCoverageInput = ProgramDesc::kSolidWhite_ColorInput;
532 } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeCoverage) {
533 desc->fCoverageInput = ProgramDesc::kUniform_ColorInput;
534 } else {
535 desc->fCoverageInput = ProgramDesc::kAttribute_ColorInput;
536 }
537
538 int lastEnabledStage = -1;
539
540 if (!skipCoverage && (desc->fVertexLayout &GrDrawState::kEdge_VertexLayoutBit)) {
541 desc->fVertexEdgeType = drawState.getVertexEdgeType();
542 desc->fDiscardIfOutsideEdge = drawState.getStencil().doesWrite();
543 } else {
544 // Use canonical values when edge-aa is not enabled to avoid program cache misses.
545 desc->fVertexEdgeType = GrDrawState::kHairLine_EdgeType;
546 desc->fDiscardIfOutsideEdge = false;
547 }
548
549 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
550
551 bool skip = s < drawState.getFirstCoverageStage() ? skipColor : skipCoverage;
552 if (!skip && drawState.isStageEnabled(s)) {
553 lastEnabledStage = s;
554 const GrEffectRef& effect = *drawState.getStage(s).getEffect();
555 const GrBackendEffectFactory& factory = effect->getFactory();
556 desc->fEffectKeys[s] = factory.glEffectKey(drawState.getStage(s), this->glCaps());
557 } else {
558 desc->fEffectKeys[s] = 0;
559 }
560 }
561
562 desc->fDualSrcOutput = ProgramDesc::kNone_DualSrcOutput;
563
564 // Currently the experimental GS will only work with triangle prims (and it doesn't do anything
565 // other than pass through values from the VS to the FS anyway).
566 #if 0 && GR_GL_EXPERIMENTAL_GS
567 desc->fExperimentalGS = this->getCaps().fGeometryShaderSupport;
568 #endif
569
570 // We want to avoid generating programs with different "first cov stage" values when they would
571 // compute the same result. We set field in the desc to kNumStages when either there are no
572 // coverage stages or the distinction between coverage and color is immaterial.
573 int firstCoverageStage = GrDrawState::kNumStages;
574 desc->fFirstCoverageStage = GrDrawState::kNumStages;
575 bool hasCoverage = drawState.getFirstCoverageStage() <= lastEnabledStage;
576 if (hasCoverage) {
577 firstCoverageStage = drawState.getFirstCoverageStage();
578 }
579
580 // other coverage inputs
581 if (!hasCoverage) {
582 hasCoverage = requiresAttributeCoverage ||
583 (desc->fVertexLayout & GrDrawState::kEdge_VertexLayoutBit);
584 }
585
586 if (hasCoverage) {
587 // color filter is applied between color/coverage computation
588 if (SkXfermode::kDst_Mode != desc->fColorFilterXfermode) {
589 desc->fFirstCoverageStage = firstCoverageStage;
590 }
591
592 if (this->getCaps().dualSourceBlendingSupport() &&
593 !(blendOpts & (kEmitCoverage_BlendOptFlag | kCoverageAsAlpha_BlendOptFlag))) {
594 if (kZero_GrBlendCoeff == dstCoeff) {
595 // write the coverage value to second color
596 desc->fDualSrcOutput = ProgramDesc::kCoverage_DualSrcOutput;
597 desc->fFirstCoverageStage = firstCoverageStage;
598 } else if (kSA_GrBlendCoeff == dstCoeff) {
599 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
600 desc->fDualSrcOutput = ProgramDesc::kCoverageISA_DualSrcOutput;
601 desc->fFirstCoverageStage = firstCoverageStage;
602 } else if (kSC_GrBlendCoeff == dstCoeff) {
603 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
604 desc->fDualSrcOutput = ProgramDesc::kCoverageISC_DualSrcOutput;
605 desc->fFirstCoverageStage = firstCoverageStage;
606 }
607 }
608 }
609 }
610