blob: 98280e297cf13171b937e960055b6cee4f2e2fb6 [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
8#include "GrGLProgramDesc.h"
9#include "GrBackendEffectFactory.h"
10#include "GrDrawEffect.h"
11#include "GrEffect.h"
12#include "GrGpuGL.h"
13
14void GrGLProgramDesc::Build(const GrDrawState& drawState,
15 bool isPoints,
16 GrDrawState::BlendOptFlags blendOpts,
17 GrBlendCoeff srcCoeff,
18 GrBlendCoeff dstCoeff,
19 const GrGpuGL* gpu,
20 GrGLProgramDesc* desc) {
21
22 // This should already have been caught
23 GrAssert(!(GrDrawState::kSkipDraw_BlendOptFlag & blendOpts));
24
25 bool skipCoverage = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag);
26
27 bool skipColor = SkToBool(blendOpts & (GrDrawState::kEmitTransBlack_BlendOptFlag |
28 GrDrawState::kEmitCoverage_BlendOptFlag));
29
30 // The descriptor is used as a cache key. Thus when a field of the
31 // descriptor will not affect program generation (because of the attribute
32 // bindings in use or other descriptor field settings) it should be set
33 // to a canonical value to avoid duplicate programs with different keys.
34
35 // Must initialize all fields or cache will have false negatives!
36 desc->fAttribBindings = drawState.getAttribBindings();
37
38 desc->fEmitsPointSize = isPoints;
39
40 bool requiresAttributeColors =
41 !skipColor && SkToBool(desc->fAttribBindings & GrDrawState::kColor_AttribBindingsBit);
42 bool requiresAttributeCoverage =
43 !skipCoverage && SkToBool(desc->fAttribBindings & GrDrawState::kCoverage_AttribBindingsBit);
44
45 // fColorInput/fCoverageInput records how colors are specified for the program so we strip the
46 // bits from the bindings to avoid false negatives when searching for an existing program in the
47 // cache.
48 desc->fAttribBindings &=
49 ~(GrDrawState::kColor_AttribBindingsBit | GrDrawState::kCoverage_AttribBindingsBit);
50
51 desc->fColorFilterXfermode = skipColor ? SkXfermode::kDst_Mode : drawState.getColorFilterMode();
52
53 // no reason to do edge aa or look at per-vertex coverage if coverage is ignored
54 if (skipCoverage) {
55 desc->fAttribBindings &= ~(GrDrawState::kCoverage_AttribBindingsBit);
56 }
57
58 bool colorIsTransBlack = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag);
59 bool colorIsSolidWhite = (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) ||
60 (!requiresAttributeColors && 0xffffffff == drawState.getColor());
61 if (colorIsTransBlack) {
62 desc->fColorInput = kTransBlack_ColorInput;
63 } else if (colorIsSolidWhite) {
64 desc->fColorInput = kSolidWhite_ColorInput;
65 } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeColors) {
66 desc->fColorInput = kUniform_ColorInput;
67 } else {
68 desc->fColorInput = kAttribute_ColorInput;
69 }
70
71 bool covIsSolidWhite = !requiresAttributeCoverage && 0xffffffff == drawState.getCoverage();
72
73 if (skipCoverage) {
74 desc->fCoverageInput = kTransBlack_ColorInput;
75 } else if (covIsSolidWhite) {
76 desc->fCoverageInput = kSolidWhite_ColorInput;
77 } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeCoverage) {
78 desc->fCoverageInput = kUniform_ColorInput;
79 } else {
80 desc->fCoverageInput = kAttribute_ColorInput;
81 }
82
83 int lastEnabledStage = -1;
84
85 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
86
87 bool skip = s < drawState.getFirstCoverageStage() ? skipColor : skipCoverage;
88 if (!skip && drawState.isStageEnabled(s)) {
89 lastEnabledStage = s;
90 const GrEffectRef& effect = *drawState.getStage(s).getEffect();
91 const GrBackendEffectFactory& factory = effect->getFactory();
92 bool explicitLocalCoords = (drawState.getAttribBindings() &
93 GrDrawState::kLocalCoords_AttribBindingsBit);
94 GrDrawEffect drawEffect(drawState.getStage(s), explicitLocalCoords);
95 desc->fEffectKeys[s] = factory.glEffectKey(drawEffect, gpu->glCaps());
96 } else {
97 desc->fEffectKeys[s] = 0;
98 }
99 }
100
101 desc->fDualSrcOutput = kNone_DualSrcOutput;
102
103 // Currently the experimental GS will only work with triangle prims (and it doesn't do anything
104 // other than pass through values from the VS to the FS anyway).
105#if GR_GL_EXPERIMENTAL_GS
106#if 0
107 desc->fExperimentalGS = gpu->caps().geometryShaderSupport();
108#else
109 desc->fExperimentalGS = false;
110#endif
111#endif
112
113 // We leave this set to kNumStages until we discover that the coverage/color distinction is
114 // material to the generated program. We do this to avoid distinct keys that generate equivalent
115 // programs.
116 desc->fFirstCoverageStage = GrDrawState::kNumStages;
117 // This tracks the actual first coverage stage.
118 int firstCoverageStage = GrDrawState::kNumStages;
119 desc->fDiscardIfZeroCoverage = false; // Enabled below if stenciling and there is coverage.
120 bool hasCoverage = false;
121 // If we're rendering coverage-as-color then it's as though there are no coverage stages.
122 if (!drawState.isCoverageDrawing()) {
123 // We can have coverage either through a stage or coverage vertex attributes.
124 if (drawState.getFirstCoverageStage() <= lastEnabledStage) {
125 firstCoverageStage = drawState.getFirstCoverageStage();
126 hasCoverage = true;
127 } else {
128 hasCoverage = requiresAttributeCoverage;
129 }
130 }
131
132 if (hasCoverage) {
133 // color filter is applied between color/coverage computation
134 if (SkXfermode::kDst_Mode != desc->fColorFilterXfermode) {
135 desc->fFirstCoverageStage = firstCoverageStage;
136 }
137
138 // If we're stenciling then we want to discard samples that have zero coverage
139 if (drawState.getStencil().doesWrite()) {
140 desc->fDiscardIfZeroCoverage = true;
141 desc->fFirstCoverageStage = firstCoverageStage;
142 }
143
144 if (gpu->caps()->dualSourceBlendingSupport() &&
145 !(blendOpts & (GrDrawState::kEmitCoverage_BlendOptFlag |
146 GrDrawState::kCoverageAsAlpha_BlendOptFlag))) {
147 if (kZero_GrBlendCoeff == dstCoeff) {
148 // write the coverage value to second color
149 desc->fDualSrcOutput = kCoverage_DualSrcOutput;
150 desc->fFirstCoverageStage = firstCoverageStage;
151 } else if (kSA_GrBlendCoeff == dstCoeff) {
152 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
153 desc->fDualSrcOutput = kCoverageISA_DualSrcOutput;
154 desc->fFirstCoverageStage = firstCoverageStage;
155 } else if (kSC_GrBlendCoeff == dstCoeff) {
156 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
157 desc->fDualSrcOutput = kCoverageISC_DualSrcOutput;
158 desc->fFirstCoverageStage = firstCoverageStage;
159 }
160 }
161 }
162
163 desc->fPositionAttributeIndex = drawState.getAttribIndex(GrDrawState::kPosition_AttribIndex);
164 if (requiresAttributeColors) {
165 desc->fColorAttributeIndex = drawState.getAttribIndex(GrDrawState::kColor_AttribIndex);
166 } else {
167 desc->fColorAttributeIndex = GrDrawState::kColorOverrideAttribIndexValue;
168 }
169 if (requiresAttributeCoverage) {
170 desc->fCoverageAttributeIndex = drawState.getAttribIndex(GrDrawState::kCoverage_AttribIndex);
171 } else {
172 desc->fCoverageAttributeIndex = GrDrawState::kCoverageOverrideAttribIndexValue;
173 }
174 if (desc->fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) {
175 desc->fLocalCoordsAttributeIndex = drawState.getAttribIndex(GrDrawState::kLocalCoords_AttribIndex);
176 }
177
178#if GR_DEBUG
179 // Verify valid vertex attribute state. These assertions should probably be done somewhere
180 // higher up the callstack
181 const GrVertexAttrib* vertexAttribs = drawState.getVertexAttribs();
182 GrAssert(desc->fPositionAttributeIndex < GrDrawState::kVertexAttribCnt);
183 GrAssert(GrGLAttribTypeToLayout(vertexAttribs[desc->fPositionAttributeIndex].fType).fCount == 2);
184 if (requiresAttributeColors) {
185 GrAssert(desc->fColorAttributeIndex < GrDrawState::kVertexAttribCnt);
186 GrAssert(GrGLAttribTypeToLayout(vertexAttribs[desc->fColorAttributeIndex].fType).fCount == 4);
187 }
188 if (requiresAttributeCoverage) {
189 GrAssert(desc->fCoverageAttributeIndex < GrDrawState::kVertexAttribCnt);
190 GrAssert(GrGLAttribTypeToLayout(vertexAttribs[desc->fCoverageAttributeIndex].fType).fCount == 4);
191 }
192 if (desc->fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) {
193 GrAssert(desc->fLocalCoordsAttributeIndex < GrDrawState::kVertexAttribCnt);
194 GrAssert(GrGLAttribTypeToLayout(vertexAttribs[desc->fLocalCoordsAttributeIndex].fType).fCount == 2);
195 }
196#endif
197}