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