blob: a1cd85e9f4afb6d5ad2770fd9ac03a50292ccdca [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.com798c8c42013-03-27 19:50:27 +000079 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();
jvanverth@google.com054ae992013-04-01 20:06:51 +000088 GrDrawEffect drawEffect(drawState.getStage(s), requiresLocalCoordAttrib);
bsalomon@google.com798c8c42013-03-27 19:50:27 +000089 desc->fEffectKeys[s] = factory.glEffectKey(drawEffect, gpu->glCaps());
commit-bot@chromium.org8d47ddc2013-05-09 14:55:46 +000090 if (effect->willReadDstColor()) {
bsalomon@google.com26e18b52013-03-29 19:22:36 +000091 readsDst = true;
92 }
bsalomon@google.com798c8c42013-03-27 19:50:27 +000093 } else {
94 desc->fEffectKeys[s] = 0;
95 }
96 }
97
bsalomon@google.com26e18b52013-03-29 19:22:36 +000098 if (readsDst) {
bsalomon@google.com6b0cf022013-05-03 13:35:14 +000099 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());
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000105 GrAssert(0 != desc->fDstRead);
106 } else {
107 desc->fDstRead = 0;
108 }
109
bsalomon@google.com5920ac22013-04-19 13:14:45 +0000110 desc->fCoverageOutput = kModulate_CoverageOutput;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000111
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 {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000137 hasCoverage = requiresCoverageAttrib;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000138 }
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
bsalomon@google.com5920ac22013-04-19 13:14:45 +0000158 desc->fCoverageOutput = kSecondaryCoverage_CoverageOutput;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000159 desc->fFirstCoverageStage = firstCoverageStage;
160 } else if (kSA_GrBlendCoeff == dstCoeff) {
161 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
bsalomon@google.com5920ac22013-04-19 13:14:45 +0000162 desc->fCoverageOutput = kSecondaryCoverageISA_CoverageOutput;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000163 desc->fFirstCoverageStage = firstCoverageStage;
164 } else if (kSC_GrBlendCoeff == dstCoeff) {
165 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
bsalomon@google.com5920ac22013-04-19 13:14:45 +0000166 desc->fCoverageOutput = kSecondaryCoverageISC_CoverageOutput;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000167 desc->fFirstCoverageStage = firstCoverageStage;
168 }
bsalomon@google.com5920ac22013-04-19 13:14:45 +0000169 } else if (readsDst &&
170 kOne_GrBlendCoeff == drawState.getSrcBlendCoeff() &&
171 kZero_GrBlendCoeff == drawState.getDstBlendCoeff()) {
172 desc->fCoverageOutput = kCombineWithDst_CoverageOutput;
173 desc->fFirstCoverageStage = firstCoverageStage;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000174 }
175 }
176
jvanverth@google.com054ae992013-04-01 20:06:51 +0000177 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++;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000188 } else {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000189 desc->fColorAttributeIndex = -1;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000190 }
191
jvanverth@google.com054ae992013-04-01 20:06:51 +0000192 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;
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000199 }
bsalomon@google.com798c8c42013-03-27 19:50:27 +0000200}