blob: 532923a19c0d4c3e6907bf761441423896abaffd [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
bsalomon@google.com798c8c42013-03-27 19:50:27 +000037
38 desc->fEmitsPointSize = isPoints;
39
jvanverth@google.com054ae992013-04-01 20:06:51 +000040 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();
bsalomon@google.com798c8c42013-03-27 19:50:27 +000045
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.
bsalomon@google.com798c8c42013-03-27 19:50:27 +000049
50 desc->fColorFilterXfermode = skipColor ? SkXfermode::kDst_Mode : drawState.getColorFilterMode();
51
bsalomon@google.com798c8c42013-03-27 19:50:27 +000052
53 bool colorIsTransBlack = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag);
54 bool colorIsSolidWhite = (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) ||
jvanverth@google.com054ae992013-04-01 20:06:51 +000055 (!requiresColorAttrib && 0xffffffff == drawState.getColor());
bsalomon@google.com798c8c42013-03-27 19:50:27 +000056 if (colorIsTransBlack) {
57 desc->fColorInput = kTransBlack_ColorInput;
58 } else if (colorIsSolidWhite) {
59 desc->fColorInput = kSolidWhite_ColorInput;
jvanverth@google.com054ae992013-04-01 20:06:51 +000060 } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresColorAttrib) {
bsalomon@google.com798c8c42013-03-27 19:50:27 +000061 desc->fColorInput = kUniform_ColorInput;
62 } else {
63 desc->fColorInput = kAttribute_ColorInput;
64 }
65
jvanverth@google.com054ae992013-04-01 20:06:51 +000066 bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverage();
bsalomon@google.com798c8c42013-03-27 19:50:27 +000067
68 if (skipCoverage) {
69 desc->fCoverageInput = kTransBlack_ColorInput;
70 } else if (covIsSolidWhite) {
71 desc->fCoverageInput = kSolidWhite_ColorInput;
jvanverth@google.com054ae992013-04-01 20:06:51 +000072 } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresCoverageAttrib) {
bsalomon@google.com798c8c42013-03-27 19:50:27 +000073 desc->fCoverageInput = kUniform_ColorInput;
74 } else {
75 desc->fCoverageInput = kAttribute_ColorInput;
76 }
77
bsalomon@google.com26e18b52013-03-29 19:22:36 +000078 bool readsDst = false;
bsalomon@google.comb5158812013-05-13 18:50:25 +000079 bool readFragPosition = false;
bsalomon@google.com798c8c42013-03-27 19:50:27 +000080 int lastEnabledStage = -1;
81
82 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
83
84 bool skip = s < drawState.getFirstCoverageStage() ? skipColor : skipCoverage;
85 if (!skip && drawState.isStageEnabled(s)) {
86 lastEnabledStage = s;
87 const GrEffectRef& effect = *drawState.getStage(s).getEffect();
88 const GrBackendEffectFactory& factory = effect->getFactory();
jvanverth@google.com054ae992013-04-01 20:06:51 +000089 GrDrawEffect drawEffect(drawState.getStage(s), requiresLocalCoordAttrib);
bsalomon@google.com798c8c42013-03-27 19:50:27 +000090 desc->fEffectKeys[s] = factory.glEffectKey(drawEffect, gpu->glCaps());
commit-bot@chromium.org8d47ddc2013-05-09 14:55:46 +000091 if (effect->willReadDstColor()) {
bsalomon@google.com26e18b52013-03-29 19:22:36 +000092 readsDst = true;
93 }
bsalomon@google.comb5158812013-05-13 18:50:25 +000094 if (effect->willReadFragmentPosition()) {
95 readFragPosition = true;
96 }
bsalomon@google.com798c8c42013-03-27 19:50:27 +000097 } else {
98 desc->fEffectKeys[s] = 0;
99 }
100 }
101
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000102 if (readsDst) {
bsalomon@google.com6b0cf022013-05-03 13:35:14 +0000103 GrAssert(NULL != dstCopy || gpu->caps()->dstReadInShaderSupport());
104 const GrTexture* dstCopyTexture = NULL;
105 if (NULL != dstCopy) {
106 dstCopyTexture = dstCopy->texture();
107 }
bsalomon@google.comb5158812013-05-13 18:50:25 +0000108 desc->fDstReadKey = GrGLShaderBuilder::KeyForDstRead(dstCopyTexture, gpu->glCaps());
109 GrAssert(0 != desc->fDstReadKey);
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000110 } else {
bsalomon@google.comb5158812013-05-13 18:50:25 +0000111 desc->fDstReadKey = 0;
112 }
113
114 if (readFragPosition) {
115 desc->fFragPosKey = GrGLShaderBuilder::KeyForFragmentPosition(drawState.getRenderTarget(),
116 gpu->glCaps());
117 } else {
118 desc->fFragPosKey = 0;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000119 }
120
bsalomon@google.com5920ac22013-04-19 13:14:45 +0000121 desc->fCoverageOutput = kModulate_CoverageOutput;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000122
123 // Currently the experimental GS will only work with triangle prims (and it doesn't do anything
124 // other than pass through values from the VS to the FS anyway).
125#if GR_GL_EXPERIMENTAL_GS
126#if 0
127 desc->fExperimentalGS = gpu->caps().geometryShaderSupport();
128#else
129 desc->fExperimentalGS = false;
130#endif
131#endif
132
133 // We leave this set to kNumStages until we discover that the coverage/color distinction is
134 // material to the generated program. We do this to avoid distinct keys that generate equivalent
135 // programs.
136 desc->fFirstCoverageStage = GrDrawState::kNumStages;
137 // This tracks the actual first coverage stage.
138 int firstCoverageStage = GrDrawState::kNumStages;
139 desc->fDiscardIfZeroCoverage = false; // Enabled below if stenciling and there is coverage.
140 bool hasCoverage = false;
141 // If we're rendering coverage-as-color then it's as though there are no coverage stages.
142 if (!drawState.isCoverageDrawing()) {
143 // We can have coverage either through a stage or coverage vertex attributes.
144 if (drawState.getFirstCoverageStage() <= lastEnabledStage) {
145 firstCoverageStage = drawState.getFirstCoverageStage();
146 hasCoverage = true;
147 } else {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000148 hasCoverage = requiresCoverageAttrib;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000149 }
150 }
151
152 if (hasCoverage) {
153 // color filter is applied between color/coverage computation
154 if (SkXfermode::kDst_Mode != desc->fColorFilterXfermode) {
155 desc->fFirstCoverageStage = firstCoverageStage;
156 }
157
158 // If we're stenciling then we want to discard samples that have zero coverage
159 if (drawState.getStencil().doesWrite()) {
160 desc->fDiscardIfZeroCoverage = true;
161 desc->fFirstCoverageStage = firstCoverageStage;
162 }
163
164 if (gpu->caps()->dualSourceBlendingSupport() &&
165 !(blendOpts & (GrDrawState::kEmitCoverage_BlendOptFlag |
166 GrDrawState::kCoverageAsAlpha_BlendOptFlag))) {
167 if (kZero_GrBlendCoeff == dstCoeff) {
168 // write the coverage value to second color
bsalomon@google.com5920ac22013-04-19 13:14:45 +0000169 desc->fCoverageOutput = kSecondaryCoverage_CoverageOutput;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000170 desc->fFirstCoverageStage = firstCoverageStage;
171 } else if (kSA_GrBlendCoeff == dstCoeff) {
172 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
bsalomon@google.com5920ac22013-04-19 13:14:45 +0000173 desc->fCoverageOutput = kSecondaryCoverageISA_CoverageOutput;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000174 desc->fFirstCoverageStage = firstCoverageStage;
175 } else if (kSC_GrBlendCoeff == dstCoeff) {
176 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
bsalomon@google.com5920ac22013-04-19 13:14:45 +0000177 desc->fCoverageOutput = kSecondaryCoverageISC_CoverageOutput;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000178 desc->fFirstCoverageStage = firstCoverageStage;
179 }
bsalomon@google.com5920ac22013-04-19 13:14:45 +0000180 } else if (readsDst &&
181 kOne_GrBlendCoeff == drawState.getSrcBlendCoeff() &&
182 kZero_GrBlendCoeff == drawState.getDstBlendCoeff()) {
183 desc->fCoverageOutput = kCombineWithDst_CoverageOutput;
184 desc->fFirstCoverageStage = firstCoverageStage;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000185 }
186 }
187
jvanverth@google.com054ae992013-04-01 20:06:51 +0000188 desc->fPositionAttributeIndex = drawState.positionAttributeIndex();
189 desc->fLocalCoordAttributeIndex = drawState.localCoordAttributeIndex();
190
191 // For constant color and coverage we need an attribute with an index beyond those already set
192 int availableAttributeIndex = drawState.getVertexAttribCount();
193 if (requiresColorAttrib) {
194 desc->fColorAttributeIndex = drawState.colorVertexAttributeIndex();
195 } else if (GrGLProgramDesc::kAttribute_ColorInput == desc->fColorInput) {
196 GrAssert(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
197 desc->fColorAttributeIndex = availableAttributeIndex;
198 availableAttributeIndex++;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000199 } else {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000200 desc->fColorAttributeIndex = -1;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000201 }
202
jvanverth@google.com054ae992013-04-01 20:06:51 +0000203 if (requiresCoverageAttrib) {
204 desc->fCoverageAttributeIndex = drawState.coverageVertexAttributeIndex();
205 } else if (GrGLProgramDesc::kAttribute_ColorInput == desc->fCoverageInput) {
206 GrAssert(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
207 desc->fCoverageAttributeIndex = availableAttributeIndex;
208 } else {
209 desc->fCoverageAttributeIndex = -1;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000210 }
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000211}