GrGpuGL_program.cpp revision cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9
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
14typedef GrGLUniformManager::UniformHandle UniformHandle;
15static const UniformHandle kInvalidUniformHandle = GrGLUniformManager::kInvalidUniformHandle;
16
17#define SKIP_CACHE_CHECK    true
18#define GR_UINT32_MAX   static_cast<uint32_t>(-1)
19
20GrGpuGL::ProgramCache::ProgramCache(const GrGLContextInfo& gl)
21    : fCount(0)
22    , fCurrLRUStamp(0)
23    , fGL(gl) {
24}
25
26void 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
35GrGLProgram* 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
76void 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
86void 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
164void 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
212void 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
257bool 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
343void GrGpuGL::setupGeometry(int* startVertex,
344                            int* startIndex,
345                            int vertexCount,
346                            int indexCount) {
347
348    int newColorOffset;
349    int newCoverageOffset;
350    int newTexCoordOffsets[GrDrawState::kMaxTexCoords];
351    int newEdgeOffset;
352
353    GrVertexLayout currLayout = this->getVertexLayout();
354
355    GrGLsizei newStride = GrDrawState::VertexSizeAndOffsetsByIdx(
356                                            currLayout,
357                                            newTexCoordOffsets,
358                                            &newColorOffset,
359                                            &newCoverageOffset,
360                                            &newEdgeOffset);
361    int oldColorOffset;
362    int oldCoverageOffset;
363    int oldTexCoordOffsets[GrDrawState::kMaxTexCoords];
364    int oldEdgeOffset;
365
366    GrGLsizei oldStride = GrDrawState::VertexSizeAndOffsetsByIdx(
367                                            fHWGeometryState.fVertexLayout,
368                                            oldTexCoordOffsets,
369                                            &oldColorOffset,
370                                            &oldCoverageOffset,
371                                            &oldEdgeOffset);
372    bool indexed = NULL != startIndex;
373
374    int extraVertexOffset;
375    int extraIndexOffset;
376    this->setBuffers(indexed, &extraVertexOffset, &extraIndexOffset);
377
378    GrGLenum scalarType;
379    bool texCoordNorm;
380    if (currLayout & GrDrawState::kTextFormat_VertexLayoutBit) {
381        scalarType = TEXT_COORDS_GL_TYPE;
382        texCoordNorm = SkToBool(TEXT_COORDS_ARE_NORMALIZED);
383    } else {
384//        GR_STATIC_ASSERT(SK_SCALAR_IS_FLOAT);
385        scalarType = GR_GL_FLOAT;
386        texCoordNorm = false;
387    }
388
389    size_t vertexOffset = (*startVertex + extraVertexOffset) * newStride;
390    *startVertex = 0;
391    if (indexed) {
392        *startIndex += extraIndexOffset;
393    }
394
395    // all the Pointers must be set if any of these are true
396    bool allOffsetsChange =  fHWGeometryState.fArrayPtrsDirty ||
397                             vertexOffset != fHWGeometryState.fVertexOffset ||
398                             newStride != oldStride;
399
400    // position and tex coord offsets change if above conditions are true
401    // or the type/normalization changed based on text vs nontext type coords.
402    bool posAndTexChange = allOffsetsChange ||
403                           (((TEXT_COORDS_GL_TYPE != GR_GL_FLOAT) || TEXT_COORDS_ARE_NORMALIZED) &&
404                                (GrDrawState::kTextFormat_VertexLayoutBit &
405                                  (fHWGeometryState.fVertexLayout ^ currLayout)));
406
407    if (posAndTexChange) {
408        int idx = GrGLProgram::PositionAttributeIdx();
409        GL_CALL(VertexAttribPointer(idx, 2, scalarType, false, newStride,
410                                  (GrGLvoid*)vertexOffset));
411        fHWGeometryState.fVertexOffset = vertexOffset;
412    }
413
414    for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
415        if (newTexCoordOffsets[t] > 0) {
416            GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffsets[t]);
417            int idx = GrGLProgram::TexCoordAttributeIdx(t);
418            if (oldTexCoordOffsets[t] <= 0) {
419                GL_CALL(EnableVertexAttribArray(idx));
420                GL_CALL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm,
421                                          newStride, texCoordOffset));
422            } else if (posAndTexChange ||
423                       newTexCoordOffsets[t] != oldTexCoordOffsets[t]) {
424                GL_CALL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm,
425                                          newStride, texCoordOffset));
426            }
427        } else if (oldTexCoordOffsets[t] > 0) {
428            GL_CALL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx(t)));
429        }
430    }
431
432    if (newColorOffset > 0) {
433        GrGLvoid* colorOffset = (int8_t*)(vertexOffset + newColorOffset);
434        int idx = GrGLProgram::ColorAttributeIdx();
435        if (oldColorOffset <= 0) {
436            GL_CALL(EnableVertexAttribArray(idx));
437            GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
438                                      true, newStride, colorOffset));
439        } else if (allOffsetsChange || newColorOffset != oldColorOffset) {
440            GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
441                                      true, newStride, colorOffset));
442        }
443    } else if (oldColorOffset > 0) {
444        GL_CALL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx()));
445    }
446
447    if (newCoverageOffset > 0) {
448        GrGLvoid* coverageOffset = (int8_t*)(vertexOffset + newCoverageOffset);
449        int idx = GrGLProgram::CoverageAttributeIdx();
450        if (oldCoverageOffset <= 0) {
451            GL_CALL(EnableVertexAttribArray(idx));
452            GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
453                                        true, newStride, coverageOffset));
454        } else if (allOffsetsChange || newCoverageOffset != oldCoverageOffset) {
455            GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
456                                        true, newStride, coverageOffset));
457        }
458    } else if (oldCoverageOffset > 0) {
459        GL_CALL(DisableVertexAttribArray(GrGLProgram::CoverageAttributeIdx()));
460    }
461
462    if (newEdgeOffset > 0) {
463        GrGLvoid* edgeOffset = (int8_t*)(vertexOffset + newEdgeOffset);
464        int idx = GrGLProgram::EdgeAttributeIdx();
465        if (oldEdgeOffset <= 0) {
466            GL_CALL(EnableVertexAttribArray(idx));
467            GL_CALL(VertexAttribPointer(idx, 4, scalarType,
468                                        false, newStride, edgeOffset));
469        } else if (allOffsetsChange || newEdgeOffset != oldEdgeOffset) {
470            GL_CALL(VertexAttribPointer(idx, 4, scalarType,
471                                        false, newStride, edgeOffset));
472        }
473    } else if (oldEdgeOffset > 0) {
474        GL_CALL(DisableVertexAttribArray(GrGLProgram::EdgeAttributeIdx()));
475    }
476
477    fHWGeometryState.fVertexLayout = currLayout;
478    fHWGeometryState.fArrayPtrsDirty = false;
479}
480
481void GrGpuGL::buildProgram(bool isPoints,
482                           BlendOptFlags blendOpts,
483                           GrBlendCoeff dstCoeff,
484                           ProgramDesc* desc) {
485    const GrDrawState& drawState = this->getDrawState();
486
487    // This should already have been caught
488    GrAssert(!(kSkipDraw_BlendOptFlag & blendOpts));
489
490    bool skipCoverage = SkToBool(blendOpts & kEmitTransBlack_BlendOptFlag);
491
492    bool skipColor = SkToBool(blendOpts & (kEmitTransBlack_BlendOptFlag |
493                                           kEmitCoverage_BlendOptFlag));
494
495    // The descriptor is used as a cache key. Thus when a field of the
496    // descriptor will not affect program generation (because of the vertex
497    // layout in use or other descriptor field settings) it should be set
498    // to a canonical value to avoid duplicate programs with different keys.
499
500    // Must initialize all fields or cache will have false negatives!
501    desc->fVertexLayout = this->getVertexLayout();
502
503    desc->fEmitsPointSize = isPoints;
504
505    bool requiresAttributeColors = !skipColor &&
506                                   SkToBool(desc->fVertexLayout & GrDrawState::kColor_VertexLayoutBit);
507    bool requiresAttributeCoverage = !skipCoverage &&
508                                     SkToBool(desc->fVertexLayout & GrDrawState::kCoverage_VertexLayoutBit);
509
510    // fColorInput/fCoverageInput records how colors are specified for the.
511    // program. So we strip the bits from the layout to avoid false negatives
512    // when searching for an existing program in the cache.
513    desc->fVertexLayout &= ~(GrDrawState::kColor_VertexLayoutBit | GrDrawState::kCoverage_VertexLayoutBit);
514
515    desc->fColorFilterXfermode = skipColor ?
516                                SkXfermode::kDst_Mode :
517                                drawState.getColorFilterMode();
518
519    // no reason to do edge aa or look at per-vertex coverage if coverage is
520    // ignored
521    if (skipCoverage) {
522        desc->fVertexLayout &= ~(GrDrawState::kEdge_VertexLayoutBit | GrDrawState::kCoverage_VertexLayoutBit);
523    }
524
525    bool colorIsTransBlack = SkToBool(blendOpts & kEmitTransBlack_BlendOptFlag);
526    bool colorIsSolidWhite = (blendOpts & kEmitCoverage_BlendOptFlag) ||
527                             (!requiresAttributeColors && 0xffffffff == drawState.getColor());
528    if (GR_AGGRESSIVE_SHADER_OPTS && colorIsTransBlack) {
529        desc->fColorInput = ProgramDesc::kTransBlack_ColorInput;
530    } else if (GR_AGGRESSIVE_SHADER_OPTS && colorIsSolidWhite) {
531        desc->fColorInput = ProgramDesc::kSolidWhite_ColorInput;
532    } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeColors) {
533        desc->fColorInput = ProgramDesc::kUniform_ColorInput;
534    } else {
535        desc->fColorInput = ProgramDesc::kAttribute_ColorInput;
536    }
537
538    bool covIsSolidWhite = !requiresAttributeCoverage && 0xffffffff == drawState.getCoverage();
539
540    if (skipCoverage) {
541        desc->fCoverageInput = ProgramDesc::kTransBlack_ColorInput;
542    } else if (covIsSolidWhite) {
543        desc->fCoverageInput = ProgramDesc::kSolidWhite_ColorInput;
544    } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeCoverage) {
545        desc->fCoverageInput = ProgramDesc::kUniform_ColorInput;
546    } else {
547        desc->fCoverageInput = ProgramDesc::kAttribute_ColorInput;
548    }
549
550    int lastEnabledStage = -1;
551
552    if (!skipCoverage && (desc->fVertexLayout &GrDrawState::kEdge_VertexLayoutBit)) {
553        desc->fVertexEdgeType = drawState.getVertexEdgeType();
554        desc->fDiscardIfOutsideEdge = drawState.getStencil().doesWrite();
555    } else {
556        // Use canonical values when edge-aa is not enabled to avoid program cache misses.
557        desc->fVertexEdgeType = GrDrawState::kHairLine_EdgeType;
558        desc->fDiscardIfOutsideEdge = false;
559    }
560
561    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
562
563        bool skip = s < drawState.getFirstCoverageStage() ? skipColor : skipCoverage;
564        if (!skip && drawState.isStageEnabled(s)) {
565            lastEnabledStage = s;
566            const GrEffectRef& effect = *drawState.getStage(s).getEffect();
567            const GrBackendEffectFactory& factory = effect->getFactory();
568            desc->fEffectKeys[s] = factory.glEffectKey(drawState.getStage(s), this->glCaps());
569        } else {
570            desc->fEffectKeys[s] = 0;
571        }
572    }
573
574    desc->fDualSrcOutput = ProgramDesc::kNone_DualSrcOutput;
575
576    // Currently the experimental GS will only work with triangle prims (and it doesn't do anything
577    // other than pass through values from the VS to the FS anyway).
578#if 0 && GR_GL_EXPERIMENTAL_GS
579    desc->fExperimentalGS = this->getCaps().fGeometryShaderSupport;
580#endif
581
582    // We want to avoid generating programs with different "first cov stage" values when they would
583    // compute the same result. We set field in the desc to kNumStages when either there are no
584    // coverage stages or the distinction between coverage and color is immaterial.
585    int firstCoverageStage = GrDrawState::kNumStages;
586    desc->fFirstCoverageStage = GrDrawState::kNumStages;
587    bool hasCoverage = drawState.getFirstCoverageStage() <= lastEnabledStage;
588    if (hasCoverage) {
589        firstCoverageStage = drawState.getFirstCoverageStage();
590    }
591
592    // other coverage inputs
593    if (!hasCoverage) {
594        hasCoverage = requiresAttributeCoverage ||
595                      (desc->fVertexLayout & GrDrawState::kEdge_VertexLayoutBit);
596    }
597
598    if (hasCoverage) {
599        // color filter is applied between color/coverage computation
600        if (SkXfermode::kDst_Mode != desc->fColorFilterXfermode) {
601            desc->fFirstCoverageStage = firstCoverageStage;
602        }
603
604        if (this->getCaps().dualSourceBlendingSupport() &&
605            !(blendOpts & (kEmitCoverage_BlendOptFlag | kCoverageAsAlpha_BlendOptFlag))) {
606            if (kZero_GrBlendCoeff == dstCoeff) {
607                // write the coverage value to second color
608                desc->fDualSrcOutput =  ProgramDesc::kCoverage_DualSrcOutput;
609                desc->fFirstCoverageStage = firstCoverageStage;
610            } else if (kSA_GrBlendCoeff == dstCoeff) {
611                // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
612                desc->fDualSrcOutput = ProgramDesc::kCoverageISA_DualSrcOutput;
613                desc->fFirstCoverageStage = firstCoverageStage;
614            } else if (kSC_GrBlendCoeff == dstCoeff) {
615                // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
616                desc->fDualSrcOutput = ProgramDesc::kCoverageISC_DualSrcOutput;
617                desc->fFirstCoverageStage = firstCoverageStage;
618            }
619        }
620    }
621}
622