GrGLProgramDesc.cpp revision 8d47ddc19a40d1984bf1f384d711d36ab59fd1c0
1/*
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
8#include "GrGLProgramDesc.h"
9#include "GrBackendEffectFactory.h"
10#include "GrDrawEffect.h"
11#include "GrEffect.h"
12#include "GrGLShaderBuilder.h"
13#include "GrGpuGL.h"
14
15void GrGLProgramDesc::Build(const GrDrawState& drawState,
16                            bool isPoints,
17                            GrDrawState::BlendOptFlags blendOpts,
18                            GrBlendCoeff srcCoeff,
19                            GrBlendCoeff dstCoeff,
20                            const GrGpuGL* gpu,
21                            const GrDeviceCoordTexture* dstCopy,
22                            GrGLProgramDesc* desc) {
23
24    // This should already have been caught
25    GrAssert(!(GrDrawState::kSkipDraw_BlendOptFlag & blendOpts));
26
27    bool skipCoverage = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag);
28
29    bool skipColor = SkToBool(blendOpts & (GrDrawState::kEmitTransBlack_BlendOptFlag |
30                                           GrDrawState::kEmitCoverage_BlendOptFlag));
31
32    // The descriptor is used as a cache key. Thus when a field of the
33    // descriptor will not affect program generation (because of the attribute
34    // bindings in use or other descriptor field settings) it should be set
35    // to a canonical value to avoid duplicate programs with different keys.
36
37
38    desc->fEmitsPointSize = isPoints;
39
40    bool requiresColorAttrib = !skipColor && drawState.hasColorVertexAttribute();
41    bool requiresCoverageAttrib = !skipCoverage && drawState.hasCoverageVertexAttribute();
42    // we only need the local coords if we're actually going to generate effect code
43    bool requiresLocalCoordAttrib = !(skipCoverage  && skipColor) &&
44                                    drawState.hasLocalCoordAttribute();
45
46    // fColorInput/fCoverageInput records how colors are specified for the program so we strip the
47    // bits from the bindings to avoid false negatives when searching for an existing program in the
48    // cache.
49
50    desc->fColorFilterXfermode = skipColor ? SkXfermode::kDst_Mode : drawState.getColorFilterMode();
51
52
53    bool colorIsTransBlack = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag);
54    bool colorIsSolidWhite = (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) ||
55                             (!requiresColorAttrib && 0xffffffff == drawState.getColor());
56    if (colorIsTransBlack) {
57        desc->fColorInput = kTransBlack_ColorInput;
58    } else if (colorIsSolidWhite) {
59        desc->fColorInput = kSolidWhite_ColorInput;
60    } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresColorAttrib) {
61        desc->fColorInput = kUniform_ColorInput;
62    } else {
63        desc->fColorInput = kAttribute_ColorInput;
64    }
65
66    bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverage();
67
68    if (skipCoverage) {
69        desc->fCoverageInput = kTransBlack_ColorInput;
70    } else if (covIsSolidWhite) {
71        desc->fCoverageInput = kSolidWhite_ColorInput;
72    } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresCoverageAttrib) {
73        desc->fCoverageInput = kUniform_ColorInput;
74    } else {
75        desc->fCoverageInput = kAttribute_ColorInput;
76    }
77
78    bool readsDst = false;
79    int lastEnabledStage = -1;
80
81    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
82
83        bool skip = s < drawState.getFirstCoverageStage() ? skipColor : skipCoverage;
84        if (!skip && drawState.isStageEnabled(s)) {
85            lastEnabledStage = s;
86            const GrEffectRef& effect = *drawState.getStage(s).getEffect();
87            const GrBackendEffectFactory& factory = effect->getFactory();
88            GrDrawEffect drawEffect(drawState.getStage(s), requiresLocalCoordAttrib);
89            desc->fEffectKeys[s] = factory.glEffectKey(drawEffect, gpu->glCaps());
90            if (effect->willReadDstColor()) {
91                readsDst = true;
92            }
93        } else {
94            desc->fEffectKeys[s] = 0;
95        }
96    }
97
98    if (readsDst) {
99        GrAssert(NULL != dstCopy || gpu->caps()->dstReadInShaderSupport());
100        const GrTexture* dstCopyTexture = NULL;
101        if (NULL != dstCopy) {
102            dstCopyTexture = dstCopy->texture();
103        }
104        desc->fDstRead = GrGLShaderBuilder::KeyForDstRead(dstCopyTexture, gpu->glCaps());
105        GrAssert(0 != desc->fDstRead);
106    } else {
107        desc->fDstRead = 0;
108    }
109
110    desc->fCoverageOutput = kModulate_CoverageOutput;
111
112    // Currently the experimental GS will only work with triangle prims (and it doesn't do anything
113    // other than pass through values from the VS to the FS anyway).
114#if GR_GL_EXPERIMENTAL_GS
115#if 0
116    desc->fExperimentalGS = gpu->caps().geometryShaderSupport();
117#else
118    desc->fExperimentalGS = false;
119#endif
120#endif
121
122    // We leave this set to kNumStages until we discover that the coverage/color distinction is
123    // material to the generated program. We do this to avoid distinct keys that generate equivalent
124    // programs.
125    desc->fFirstCoverageStage = GrDrawState::kNumStages;
126    // This tracks the actual first coverage stage.
127    int firstCoverageStage = GrDrawState::kNumStages;
128    desc->fDiscardIfZeroCoverage = false; // Enabled below if stenciling and there is coverage.
129    bool hasCoverage = false;
130    // If we're rendering coverage-as-color then it's as though there are no coverage stages.
131    if (!drawState.isCoverageDrawing()) {
132        // We can have coverage either through a stage or coverage vertex attributes.
133        if (drawState.getFirstCoverageStage() <= lastEnabledStage) {
134            firstCoverageStage = drawState.getFirstCoverageStage();
135            hasCoverage = true;
136        } else {
137            hasCoverage = requiresCoverageAttrib;
138        }
139    }
140
141    if (hasCoverage) {
142        // color filter is applied between color/coverage computation
143        if (SkXfermode::kDst_Mode != desc->fColorFilterXfermode) {
144            desc->fFirstCoverageStage = firstCoverageStage;
145        }
146
147        // If we're stenciling then we want to discard samples that have zero coverage
148        if (drawState.getStencil().doesWrite()) {
149            desc->fDiscardIfZeroCoverage = true;
150            desc->fFirstCoverageStage = firstCoverageStage;
151        }
152
153        if (gpu->caps()->dualSourceBlendingSupport() &&
154            !(blendOpts & (GrDrawState::kEmitCoverage_BlendOptFlag |
155                           GrDrawState::kCoverageAsAlpha_BlendOptFlag))) {
156            if (kZero_GrBlendCoeff == dstCoeff) {
157                // write the coverage value to second color
158                desc->fCoverageOutput =  kSecondaryCoverage_CoverageOutput;
159                desc->fFirstCoverageStage = firstCoverageStage;
160            } else if (kSA_GrBlendCoeff == dstCoeff) {
161                // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
162                desc->fCoverageOutput = kSecondaryCoverageISA_CoverageOutput;
163                desc->fFirstCoverageStage = firstCoverageStage;
164            } else if (kSC_GrBlendCoeff == dstCoeff) {
165                // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
166                desc->fCoverageOutput = kSecondaryCoverageISC_CoverageOutput;
167                desc->fFirstCoverageStage = firstCoverageStage;
168            }
169        } else if (readsDst &&
170                   kOne_GrBlendCoeff == drawState.getSrcBlendCoeff() &&
171                   kZero_GrBlendCoeff == drawState.getDstBlendCoeff()) {
172            desc->fCoverageOutput = kCombineWithDst_CoverageOutput;
173            desc->fFirstCoverageStage = firstCoverageStage;
174        }
175    }
176
177    desc->fPositionAttributeIndex = drawState.positionAttributeIndex();
178    desc->fLocalCoordAttributeIndex = drawState.localCoordAttributeIndex();
179
180    // For constant color and coverage we need an attribute with an index beyond those already set
181    int availableAttributeIndex = drawState.getVertexAttribCount();
182    if (requiresColorAttrib) {
183        desc->fColorAttributeIndex = drawState.colorVertexAttributeIndex();
184    } else if (GrGLProgramDesc::kAttribute_ColorInput == desc->fColorInput) {
185        GrAssert(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
186        desc->fColorAttributeIndex = availableAttributeIndex;
187        availableAttributeIndex++;
188    } else {
189        desc->fColorAttributeIndex = -1;
190    }
191
192    if (requiresCoverageAttrib) {
193        desc->fCoverageAttributeIndex = drawState.coverageVertexAttributeIndex();
194    } else if (GrGLProgramDesc::kAttribute_ColorInput == desc->fCoverageInput) {
195        GrAssert(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
196        desc->fCoverageAttributeIndex = availableAttributeIndex;
197    } else {
198        desc->fCoverageAttributeIndex = -1;
199    }
200}
201