OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrGLFragmentShaderBuilder.h" | 8 #include "GrGLFragmentShaderBuilder.h" |
9 #include "GrGLShaderStringBuilder.h" | 9 #include "GrGLShaderStringBuilder.h" |
10 #include "GrGLProgramBuilder.h" | 10 #include "GrGLProgramBuilder.h" |
11 #include "../GrGpuGL.h" | 11 #include "../GrGpuGL.h" |
12 | 12 |
13 namespace { | 13 #define GL_CALL(X) GR_GL_CALL(fProgramBuilder->gpu()->glInterface(), X) |
14 #define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X) | 14 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(fProgramBuilder->gpu()->glInterface(),
R, X) |
15 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, X) | 15 |
16 // ES2 FS only guarantees mediump and lowp support | 16 // ES2 FS only guarantees mediump and lowp support |
17 static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar:
:kMedium_Precision; | 17 static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar:
:kMedium_Precision; |
18 static const char kDstCopyColorName[] = "_dstColor"; | 18 const char* GrGLFragmentShaderBuilder::kDstCopyColorName = "_dstColor"; |
19 inline const char* declared_color_output_name() { return "fsColorOut"; } | 19 static const char* declared_color_output_name() { return "fsColorOut"; } |
20 inline const char* dual_source_output_name() { return "dualSourceOut"; } | 20 static const char* dual_source_output_name() { return "dualSourceOut"; } |
21 inline void append_default_precision_qualifier(GrGLShaderVar::Precision p, | 21 static void append_default_precision_qualifier(GrGLShaderVar::Precision p, |
22 GrGLStandard standard, | 22 GrGLStandard standard, |
23 SkString* str) { | 23 SkString* str) { |
24 // Desktop GLSL has added precision qualifiers but they don't do anything. | 24 // Desktop GLSL has added precision qualifiers but they don't do anything. |
25 if (kGLES_GrGLStandard == standard) { | 25 if (kGLES_GrGLStandard == standard) { |
26 switch (p) { | 26 switch (p) { |
27 case GrGLShaderVar::kHigh_Precision: | 27 case GrGLShaderVar::kHigh_Precision: |
28 str->append("precision highp float;\n"); | 28 str->append("precision highp float;\n"); |
29 break; | 29 break; |
30 case GrGLShaderVar::kMedium_Precision: | 30 case GrGLShaderVar::kMedium_Precision: |
31 str->append("precision mediump float;\n"); | 31 str->append("precision mediump float;\n"); |
32 break; | 32 break; |
33 case GrGLShaderVar::kLow_Precision: | 33 case GrGLShaderVar::kLow_Precision: |
34 str->append("precision lowp float;\n"); | 34 str->append("precision lowp float;\n"); |
35 break; | 35 break; |
36 case GrGLShaderVar::kDefault_Precision: | 36 case GrGLShaderVar::kDefault_Precision: |
37 SkFAIL("Default precision now allowed."); | 37 SkFAIL("Default precision now allowed."); |
38 default: | 38 default: |
39 SkFAIL("Unknown precision value."); | 39 SkFAIL("Unknown precision value."); |
40 } | 40 } |
41 } | 41 } |
42 } | 42 } |
43 } | |
44 | 43 |
45 GrGLFragmentShaderBuilder::DstReadKey GrGLFragmentShaderBuilder::KeyForDstRead( | 44 GrGLFragmentShaderBuilder::DstReadKey |
46 const GrTexture* dstCopy, const GrGLCaps& caps) { | 45 GrGLFragmentShaderBuilder::KeyForDstRead(const GrTexture* dstCopy, |
| 46 const GrGLCaps&
caps) { |
47 uint32_t key = kYesDstRead_DstReadKeyBit; | 47 uint32_t key = kYesDstRead_DstReadKeyBit; |
48 if (caps.fbFetchSupport()) { | 48 if (caps.fbFetchSupport()) { |
49 return key; | 49 return key; |
50 } | 50 } |
51 SkASSERT(dstCopy); | 51 SkASSERT(dstCopy); |
52 if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(dstCopy->confi
g())) { | 52 if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(dstCopy->confi
g())) { |
53 // The fact that the config is alpha-only must be considered when genera
ting code. | 53 // The fact that the config is alpha-only must be considered when genera
ting code. |
54 key |= kUseAlphaConfig_DstReadKeyBit; | 54 key |= kUseAlphaConfig_DstReadKeyBit; |
55 } | 55 } |
56 if (kTopLeft_GrSurfaceOrigin == dstCopy->origin()) { | 56 if (kTopLeft_GrSurfaceOrigin == dstCopy->origin()) { |
57 key |= kTopLeftOrigin_DstReadKeyBit; | 57 key |= kTopLeftOrigin_DstReadKeyBit; |
58 } | 58 } |
59 SkASSERT(static_cast<DstReadKey>(key) == key); | 59 SkASSERT(static_cast<DstReadKey>(key) == key); |
60 return static_cast<DstReadKey>(key); | 60 return static_cast<DstReadKey>(key); |
61 } | 61 } |
62 | 62 |
63 GrGLFragmentShaderBuilder::FragPosKey GrGLFragmentShaderBuilder::KeyForFragmentP
osition( | 63 GrGLFragmentShaderBuilder::FragPosKey |
64 const GrRenderTarget* dst, const GrGLCaps&) { | 64 GrGLFragmentShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst, |
| 65 const
GrGLCaps&) { |
65 if (kTopLeft_GrSurfaceOrigin == dst->origin()) { | 66 if (kTopLeft_GrSurfaceOrigin == dst->origin()) { |
66 return kTopLeftFragPosRead_FragPosKey; | 67 return kTopLeftFragPosRead_FragPosKey; |
67 } else { | 68 } else { |
68 return kBottomLeftFragPosRead_FragPosKey; | 69 return kBottomLeftFragPosRead_FragPosKey; |
69 } | 70 } |
70 } | 71 } |
71 | 72 |
72 GrGLFragmentShaderBuilder::GrGLFragmentShaderBuilder(GrGLProgramBuilder* program
, | 73 GrGLFragmentShaderBuilder::GrGLFragmentShaderBuilder(GrGLProgramBuilder* program
, |
73 const GrGLProgramDesc& desc
) | 74 const GrGLProgramDesc& desc
) |
74 : INHERITED(program) | 75 : INHERITED(program) |
75 , fHasCustomColorOutput(false) | 76 , fHasCustomColorOutput(false) |
76 , fHasSecondaryOutput(false) | 77 , fHasSecondaryOutput(false) |
77 , fSetupFragPosition(false) | 78 , fSetupFragPosition(false) |
78 , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFr
agPosKey){ | 79 , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFr
agPosKey) |
79 } | 80 , fHasReadDstColor(false) |
80 | 81 , fHasReadFragmentPosition(false) { |
81 const char* GrGLFragmentShaderBuilder::dstColor() { | |
82 if (fProgramBuilder->fCodeStage.inStageCode()) { | |
83 const GrProcessor* effect = fProgramBuilder->fCodeStage.effectStage()->g
etProcessor(); | |
84 // TODO GPs can't read dst color, and full program builder only returns
a pointer to the | |
85 // base fragment shader builder which does not have this function. Unfo
rtunately, | |
86 // the code stage class only has a GrProcessor pointer so this is requir
ed for the time | |
87 // being | |
88 if (!static_cast<const GrFragmentProcessor*>(effect)->willReadDstColor()
) { | |
89 SkDEBUGFAIL("GrGLProcessor asked for dst color but its generating Gr
Processor " | |
90 "did not request access."); | |
91 return ""; | |
92 } | |
93 } | |
94 | |
95 GrGpuGL* gpu = fProgramBuilder->gpu(); | |
96 if (gpu->glCaps().fbFetchSupport()) { | |
97 this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeatur
e + 1), | |
98 gpu->glCaps().fbFetchExtensionString()); | |
99 return gpu->glCaps().fbFetchColorName(); | |
100 } else if (fProgramBuilder->fUniformHandles.fDstCopySamplerUni.isValid()) { | |
101 return kDstCopyColorName; | |
102 } else { | |
103 return ""; | |
104 } | |
105 } | 82 } |
106 | 83 |
107 bool GrGLFragmentShaderBuilder::enableFeature(GLSLFeature feature) { | 84 bool GrGLFragmentShaderBuilder::enableFeature(GLSLFeature feature) { |
108 switch (feature) { | 85 switch (feature) { |
109 case kStandardDerivatives_GLSLFeature: { | 86 case kStandardDerivatives_GLSLFeature: { |
110 GrGpuGL* gpu = fProgramBuilder->gpu(); | 87 GrGpuGL* gpu = fProgramBuilder->gpu(); |
111 if (!gpu->glCaps().shaderDerivativeSupport()) { | 88 if (!gpu->glCaps().shaderDerivativeSupport()) { |
112 return false; | 89 return false; |
113 } | 90 } |
114 if (kGLES_GrGLStandard == gpu->glStandard()) { | 91 if (kGLES_GrGLStandard == gpu->glStandard()) { |
(...skipping 18 matching lines...) Expand all Loading... |
133 SkString coords2D("coords2D"); | 110 SkString coords2D("coords2D"); |
134 if (0 != index) { | 111 if (0 != index) { |
135 coords2D.appendf("_%i", index); | 112 coords2D.appendf("_%i", index); |
136 } | 113 } |
137 this->codeAppendf("\tvec2 %s = %s.xy / %s.z;", | 114 this->codeAppendf("\tvec2 %s = %s.xy / %s.z;", |
138 coords2D.c_str(), coords[index].c_str(), coords[index].c_s
tr()); | 115 coords2D.c_str(), coords[index].c_str(), coords[index].c_s
tr()); |
139 return coords2D; | 116 return coords2D; |
140 } | 117 } |
141 | 118 |
142 const char* GrGLFragmentShaderBuilder::fragmentPosition() { | 119 const char* GrGLFragmentShaderBuilder::fragmentPosition() { |
143 GrGLProgramBuilder::CodeStage* cs = &fProgramBuilder->fCodeStage; | 120 fHasReadFragmentPosition = true; |
144 if (cs->inStageCode()) { | |
145 const GrProcessor* effect = cs->effectStage()->getProcessor(); | |
146 if (!effect->willReadFragmentPosition()) { | |
147 SkDEBUGFAIL("GrGLProcessor asked for frag position but its generatin
g GrProcessor " | |
148 "did not request access."); | |
149 return ""; | |
150 } | |
151 } | |
152 | 121 |
153 GrGpuGL* gpu = fProgramBuilder->gpu(); | 122 GrGpuGL* gpu = fProgramBuilder->gpu(); |
154 // We only declare "gl_FragCoord" when we're in the case where we want to us
e layout qualifiers | 123 // We only declare "gl_FragCoord" when we're in the case where we want to us
e layout qualifiers |
155 // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier
appears in the | 124 // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier
appears in the |
156 // declaration varies in earlier GLSL specs. So it is simpler to omit it. | 125 // declaration varies in earlier GLSL specs. So it is simpler to omit it. |
157 if (fTopLeftFragPosRead) { | 126 if (fTopLeftFragPosRead) { |
158 fSetupFragPosition = true; | 127 fSetupFragPosition = true; |
159 return "gl_FragCoord"; | 128 return "gl_FragCoord"; |
160 } else if (gpu->glCaps().fragCoordConventionsSupport()) { | 129 } else if (gpu->glCaps().fragCoordConventionsSupport()) { |
161 if (!fSetupFragPosition) { | 130 if (!fSetupFragPosition) { |
162 if (gpu->glslGeneration() < k150_GrGLSLGeneration) { | 131 if (gpu->glslGeneration() < k150_GrGLSLGeneration) { |
163 this->addFeature(1 << kFragCoordConventions_GLSLPrivateFeature, | 132 this->addFeature(1 << kFragCoordConventions_GLSLPrivateFeature, |
164 "GL_ARB_fragment_coord_conventions"); | 133 "GL_ARB_fragment_coord_conventions"); |
165 } | 134 } |
166 fInputs.push_back().set(kVec4f_GrSLType, | 135 fInputs.push_back().set(kVec4f_GrSLType, |
167 GrGLShaderVar::kIn_TypeModifier, | 136 GrGLShaderVar::kIn_TypeModifier, |
168 "gl_FragCoord", | 137 "gl_FragCoord", |
169 GrGLShaderVar::kDefault_Precision, | 138 GrGLShaderVar::kDefault_Precision, |
170 GrGLShaderVar::kUpperLeft_Origin); | 139 GrGLShaderVar::kUpperLeft_Origin); |
171 fSetupFragPosition = true; | 140 fSetupFragPosition = true; |
172 } | 141 } |
173 return "gl_FragCoord"; | 142 return "gl_FragCoord"; |
174 } else { | 143 } else { |
175 static const char* kCoordName = "fragCoordYDown"; | 144 static const char* kCoordName = "fragCoordYDown"; |
176 if (!fSetupFragPosition) { | 145 if (!fSetupFragPosition) { |
177 // temporarily change the stage index because we're inserting non-st
age code. | 146 // temporarily change the stage index because we're inserting non-st
age code. |
178 GrGLProgramBuilder::CodeStage::AutoStageRestore csar(cs, NULL); | 147 GrGLProgramBuilder::AutoStageRestore asr(fProgramBuilder); |
179 | |
180 SkASSERT(!fProgramBuilder->fUniformHandles.fRTHeightUni.isValid()); | 148 SkASSERT(!fProgramBuilder->fUniformHandles.fRTHeightUni.isValid()); |
181 const char* rtHeightName; | 149 const char* rtHeightName; |
182 | 150 |
183 fProgramBuilder->fUniformHandles.fRTHeightUni = | 151 fProgramBuilder->fUniformHandles.fRTHeightUni = |
184 fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Vi
sibility, | 152 fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Vi
sibility, |
185 kFloat_GrSLType, | 153 kFloat_GrSLType, |
186 "RTHeight", | 154 "RTHeight", |
187 &rtHeightName); | 155 &rtHeightName); |
188 | 156 |
189 // Using glFragCoord.zw for the last two components tickles an Adren
o driver bug that | 157 // Using glFragCoord.zw for the last two components tickles an Adren
o driver bug that |
190 // causes programs to fail to link. Making this function return a ve
c2() didn't fix the | 158 // causes programs to fail to link. Making this function return a ve
c2() didn't fix the |
191 // problem but using 1.0 for the last two components does. | 159 // problem but using 1.0 for the last two components does. |
192 this->codePrependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoo
rd.y, 1.0, " | 160 this->codePrependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoo
rd.y, 1.0, " |
193 "1.0);\n", kCoordName, rtHeightName); | 161 "1.0);\n", kCoordName, rtHeightName); |
194 fSetupFragPosition = true; | 162 fSetupFragPosition = true; |
195 } | 163 } |
196 SkASSERT(fProgramBuilder->fUniformHandles.fRTHeightUni.isValid()); | 164 SkASSERT(fProgramBuilder->fUniformHandles.fRTHeightUni.isValid()); |
197 return kCoordName; | 165 return kCoordName; |
198 } | 166 } |
199 } | 167 } |
200 | 168 |
201 void GrGLFragmentShaderBuilder::addVarying(GrSLType type, | 169 const char* GrGLFragmentShaderBuilder::dstColor() { |
202 const char* name, | 170 fHasReadDstColor = true; |
203 const char** fsInName, | 171 |
204 GrGLShaderVar::Precision fsPrecision) { | 172 GrGpuGL* gpu = fProgramBuilder->gpu(); |
205 fInputs.push_back().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, name,
fsPrecision); | 173 if (gpu->glCaps().fbFetchSupport()) { |
206 if (fsInName) { | 174 this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeatur
e + 1), |
207 *fsInName = name; | 175 gpu->glCaps().fbFetchExtensionString()); |
| 176 return gpu->glCaps().fbFetchColorName(); |
| 177 } else if (fProgramBuilder->fUniformHandles.fDstCopySamplerUni.isValid()) { |
| 178 return kDstCopyColorName; |
| 179 } else { |
| 180 return ""; |
208 } | 181 } |
209 } | 182 } |
210 | 183 |
211 void GrGLFragmentShaderBuilder::bindProgramLocations(GrGLuint programId) { | 184 void GrGLFragmentShaderBuilder::emitCodeToReadDstTexture() { |
212 GrGpuGL* gpu = fProgramBuilder->gpu(); | 185 bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & fProgramBuilder->head
er().fDstReadKey); |
213 if (fHasCustomColorOutput) { | 186 const char* dstCopyTopLeftName; |
214 GL_CALL(BindFragDataLocation(programId, 0, declared_color_output_name())
); | 187 const char* dstCopyCoordScaleName; |
| 188 const char* dstCopySamplerName; |
| 189 uint32_t configMask; |
| 190 if (SkToBool(kUseAlphaConfig_DstReadKeyBit & fProgramBuilder->header().fDstR
eadKey)) { |
| 191 configMask = kA_GrColorComponentFlag; |
| 192 } else { |
| 193 configMask = kRGBA_GrColorComponentFlags; |
215 } | 194 } |
216 if (fHasSecondaryOutput) { | 195 fProgramBuilder->fUniformHandles.fDstCopySamplerUni = |
217 GL_CALL(BindFragDataLocationIndexed(programId, 0, 1, dual_source_output_
name())); | 196 fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility
, |
| 197 kSampler2D_GrSLType, |
| 198 "DstCopySampler", |
| 199 &dstCopySamplerName); |
| 200 fProgramBuilder->fUniformHandles.fDstCopyTopLeftUni = |
| 201 fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility
, |
| 202 kVec2f_GrSLType, |
| 203 "DstCopyUpperLeft", |
| 204 &dstCopyTopLeftName); |
| 205 fProgramBuilder->fUniformHandles.fDstCopyScaleUni = |
| 206 fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility
, |
| 207 kVec2f_GrSLType, |
| 208 "DstCopyCoordScale", |
| 209 &dstCopyCoordScaleName); |
| 210 const char* fragPos = this->fragmentPosition(); |
| 211 |
| 212 this->codeAppend("// Read color from copy of the destination.\n"); |
| 213 this->codeAppendf("vec2 _dstTexCoord = (%s.xy - %s) * %s;", |
| 214 fragPos, dstCopyTopLeftName, dstCopyCoordScaleName); |
| 215 if (!topDown) { |
| 216 this->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;"); |
218 } | 217 } |
| 218 this->codeAppendf("vec4 %s = ", GrGLFragmentShaderBuilder::kDstCopyColorName
); |
| 219 this->appendTextureLookup(dstCopySamplerName, |
| 220 "_dstTexCoord", |
| 221 configMask, |
| 222 "rgba"); |
| 223 this->codeAppend(";"); |
| 224 } |
| 225 |
| 226 void GrGLFragmentShaderBuilder::enableCustomOutput() { |
| 227 SkASSERT(!fHasCustomColorOutput); |
| 228 fHasCustomColorOutput = true; |
| 229 fOutputs.push_back().set(kVec4f_GrSLType, |
| 230 GrGLShaderVar::kOut_TypeModifier, |
| 231 declared_color_output_name()); |
| 232 } |
| 233 |
| 234 void GrGLFragmentShaderBuilder::enableSecondaryOutput() { |
| 235 SkASSERT(!fHasSecondaryOutput); |
| 236 fHasSecondaryOutput = true; |
| 237 fOutputs.push_back().set(kVec4f_GrSLType, GrGLShaderVar::kOut_TypeModifier, |
| 238 dual_source_output_name()); |
| 239 } |
| 240 |
| 241 const char* GrGLFragmentShaderBuilder::getPrimaryColorOutputName() const { |
| 242 return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor"
; |
| 243 } |
| 244 |
| 245 const char* GrGLFragmentShaderBuilder::getSecondaryColorOutputName() const { |
| 246 return dual_source_output_name(); |
| 247 } |
| 248 |
| 249 void GrGLFragmentShaderBuilder::enableSecondaryOutput(const GrGLSLExpr4& inputCo
lor, |
| 250 const GrGLSLExpr4& inputCo
verage) { |
| 251 this->enableSecondaryOutput(); |
| 252 const char* secondaryOutputName = this->getSecondaryColorOutputName(); |
| 253 GrGLSLExpr4 coeff(1); |
| 254 switch (fProgramBuilder->header().fSecondaryOutputType) { |
| 255 case GrOptDrawState::kCoverage_SecondaryOutputType: |
| 256 break; |
| 257 case GrOptDrawState::kCoverageISA_SecondaryOutputType: |
| 258 // Get (1-A) into coeff |
| 259 coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inputColor.a()); |
| 260 break; |
| 261 case GrOptDrawState::kCoverageISC_SecondaryOutputType: |
| 262 // Get (1-RGBA) into coeff |
| 263 coeff = GrGLSLExpr4(1) - inputColor; |
| 264 break; |
| 265 default: |
| 266 SkFAIL("Unexpected Secondary Output"); |
| 267 } |
| 268 // Get coeff * coverage into modulate and then write that to the dual source
output. |
| 269 this->codeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inputCoverag
e).c_str()); |
| 270 } |
| 271 |
| 272 void GrGLFragmentShaderBuilder::combineColorAndCoverage(const GrGLSLExpr4& input
Color, |
| 273 const GrGLSLExpr4& input
Coverage) { |
| 274 GrGLSLExpr4 fragColor = inputColor * inputCoverage; |
| 275 switch (fProgramBuilder->header().fPrimaryOutputType) { |
| 276 case GrOptDrawState::kModulate_PrimaryOutputType: |
| 277 break; |
| 278 case GrOptDrawState::kCombineWithDst_PrimaryOutputType: |
| 279 { |
| 280 // Tack on "+(1-coverage)dst onto the frag color. |
| 281 GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inputCoverage; |
| 282 GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(this->dstCo
lor()); |
| 283 fragColor = fragColor + dstContribution; |
| 284 } |
| 285 break; |
| 286 default: |
| 287 SkFAIL("Unknown Primary Output"); |
| 288 } |
| 289 |
| 290 // On any post 1.10 GLSL supporting GPU, we declare custom output |
| 291 if (k110_GrGLSLGeneration != fProgramBuilder->gpu()->glslGeneration()) { |
| 292 this->enableCustomOutput(); |
| 293 } |
| 294 |
| 295 this->codeAppendf("\t%s = %s;\n", this->getPrimaryColorOutputName(), fragCol
or.c_str()); |
219 } | 296 } |
220 | 297 |
221 bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId, | 298 bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId, |
222 SkTDArray<GrGLuint>* sha
derIds) const { | 299 SkTDArray<GrGLuint>* sha
derIds) const { |
223 GrGpuGL* gpu = fProgramBuilder->gpu(); | 300 GrGpuGL* gpu = fProgramBuilder->gpu(); |
224 SkString fragShaderSrc(GrGetGLSLVersionDecl(gpu->ctxInfo())); | 301 SkString fragShaderSrc(GrGetGLSLVersionDecl(gpu->ctxInfo())); |
225 fragShaderSrc.append(fExtensions); | 302 fragShaderSrc.append(fExtensions); |
226 append_default_precision_qualifier(kDefaultFragmentPrecision, | 303 append_default_precision_qualifier(kDefaultFragmentPrecision, |
227 gpu->glStandard(), | 304 gpu->glStandard(), |
228 &fragShaderSrc); | 305 &fragShaderSrc); |
229 fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kFragment_Visibility
, &fragShaderSrc); | 306 fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kFragment_Visibility
, &fragShaderSrc); |
230 fProgramBuilder->appendDecls(fInputs, &fragShaderSrc); | 307 this->appendDecls(fInputs, &fragShaderSrc); |
231 // We shouldn't have declared outputs on 1.10 | 308 // We shouldn't have declared outputs on 1.10 |
232 SkASSERT(k110_GrGLSLGeneration != gpu->glslGeneration() || fOutputs.empty())
; | 309 SkASSERT(k110_GrGLSLGeneration != gpu->glslGeneration() || fOutputs.empty())
; |
233 fProgramBuilder->appendDecls(fOutputs, &fragShaderSrc); | 310 this->appendDecls(fOutputs, &fragShaderSrc); |
234 fragShaderSrc.append(fFunctions); | 311 fragShaderSrc.append(fFunctions); |
235 fragShaderSrc.append("void main() {\n"); | 312 fragShaderSrc.append("void main() {\n"); |
236 fragShaderSrc.append(fCode); | 313 fragShaderSrc.append(fCode); |
237 fragShaderSrc.append("}\n"); | 314 fragShaderSrc.append("}\n"); |
238 | 315 |
239 GrGLuint fragShaderId = GrGLCompileAndAttachShader(gpu->glContext(), program
Id, | 316 GrGLuint fragShaderId = GrGLCompileAndAttachShader(gpu->glContext(), program
Id, |
240 GR_GL_FRAGMENT_SHADER, fr
agShaderSrc, | 317 GR_GL_FRAGMENT_SHADER, fr
agShaderSrc, |
241 gpu->gpuStats()); | 318 gpu->gpuStats()); |
242 if (!fragShaderId) { | 319 if (!fragShaderId) { |
243 return false; | 320 return false; |
244 } | 321 } |
245 | 322 |
246 *shaderIds->append() = fragShaderId; | 323 *shaderIds->append() = fragShaderId; |
247 | 324 |
248 return true; | 325 return true; |
249 } | 326 } |
250 | 327 |
251 void GrGLFragmentShaderBuilder::emitCodeBeforeEffects() { | 328 void GrGLFragmentShaderBuilder::bindFragmentShaderLocations(GrGLuint programID)
{ |
252 const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader
(); | 329 if (fHasCustomColorOutput) { |
253 GrGpuGL* gpu = fProgramBuilder->gpu(); | 330 GL_CALL(BindFragDataLocation(programID, 0, declared_color_output_name())
); |
254 | |
255 /////////////////////////////////////////////////////////////////////////// | |
256 // emit code to read the dst copy texture, if necessary | |
257 if (kNoDstRead_DstReadKey != header.fDstReadKey && !gpu->glCaps().fbFetchSup
port()) { | |
258 bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKe
y); | |
259 const char* dstCopyTopLeftName; | |
260 const char* dstCopyCoordScaleName; | |
261 const char* dstCopySamplerName; | |
262 uint32_t configMask; | |
263 if (SkToBool(kUseAlphaConfig_DstReadKeyBit & header.fDstReadKey)) { | |
264 configMask = kA_GrColorComponentFlag; | |
265 } else { | |
266 configMask = kRGBA_GrColorComponentFlags; | |
267 } | |
268 fProgramBuilder->fUniformHandles.fDstCopySamplerUni = | |
269 fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility
, | |
270 kSampler2D_GrSLType, | |
271 "DstCopySampler", | |
272 &dstCopySamplerName); | |
273 fProgramBuilder->fUniformHandles.fDstCopyTopLeftUni = | |
274 fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility
, | |
275 kVec2f_GrSLType, | |
276 "DstCopyUpperLeft", | |
277 &dstCopyTopLeftName); | |
278 fProgramBuilder->fUniformHandles.fDstCopyScaleUni = | |
279 fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility
, | |
280 kVec2f_GrSLType, | |
281 "DstCopyCoordScale", | |
282 &dstCopyCoordScaleName); | |
283 const char* fragPos = fragmentPosition(); | |
284 | |
285 this->codeAppend("// Read color from copy of the destination.\n"); | |
286 this->codeAppendf("vec2 _dstTexCoord = (%s.xy - %s) * %s;", | |
287 fragPos, dstCopyTopLeftName, dstCopyCoordScaleName); | |
288 if (!topDown) { | |
289 this->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;"); | |
290 } | |
291 this->codeAppendf("vec4 %s = ", kDstCopyColorName); | |
292 this->appendTextureLookup(dstCopySamplerName, | |
293 "_dstTexCoord", | |
294 configMask, | |
295 "rgba"); | |
296 this->codeAppend(";"); | |
297 } | 331 } |
298 | 332 if (fHasSecondaryOutput) { |
299 if (k110_GrGLSLGeneration != gpu->glslGeneration()) { | 333 GL_CALL(BindFragDataLocationIndexed(programID, 0, 1, dual_source_output_
name())); |
300 fOutputs.push_back().set(kVec4f_GrSLType, | |
301 GrGLShaderVar::kOut_TypeModifier, | |
302 declared_color_output_name()); | |
303 fHasCustomColorOutput = true; | |
304 } | 334 } |
305 } | 335 } |
306 | 336 |
307 void GrGLFragmentShaderBuilder::emitCodeAfterEffects(const GrGLSLExpr4& inputCol
or, const GrGLSLExpr4& inputCoverage) { | 337 void GrGLFragmentShaderBuilder::addVarying(GrSLType type, |
308 const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader
(); | 338 const char* name, |
309 | 339 const char** fsInName, |
310 /////////////////////////////////////////////////////////////////////////// | 340 GrGLShaderVar::Precision fsPrecision) { |
311 // write the secondary color output if necessary | 341 fInputs.push_back().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, name,
fsPrecision); |
312 if (GrOptDrawState::kNone_SecondaryOutputType != header.fSecondaryOutputType
) { | 342 if (fsInName) { |
313 const char* secondaryOutputName = this->enableSecondaryOutput(); | 343 *fsInName = name; |
314 GrGLSLExpr4 coeff(1); | |
315 switch (header.fSecondaryOutputType) { | |
316 case GrOptDrawState::kCoverage_SecondaryOutputType: | |
317 break; | |
318 case GrOptDrawState::kCoverageISA_SecondaryOutputType: | |
319 // Get (1-A) into coeff | |
320 coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inputColor.a())
; | |
321 break; | |
322 case GrOptDrawState::kCoverageISC_SecondaryOutputType: | |
323 // Get (1-RGBA) into coeff | |
324 coeff = GrGLSLExpr4(1) - inputColor; | |
325 break; | |
326 default: | |
327 SkFAIL("Unexpected Secondary Output"); | |
328 } | |
329 // Get coeff * coverage into modulate and then write that to the dual so
urce output. | |
330 codeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inputCoverage)
.c_str()); | |
331 } | 344 } |
332 | |
333 /////////////////////////////////////////////////////////////////////////// | |
334 // combine color and coverage as frag color | |
335 | |
336 // Get "color * coverage" into fragColor | |
337 GrGLSLExpr4 fragColor = inputColor * inputCoverage; | |
338 switch (header.fPrimaryOutputType) { | |
339 case GrOptDrawState::kModulate_PrimaryOutputType: | |
340 break; | |
341 case GrOptDrawState::kCombineWithDst_PrimaryOutputType: | |
342 { | |
343 // Tack on "+(1-coverage)dst onto the frag color. | |
344 GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inputCoverage; | |
345 GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(dstColor())
; | |
346 fragColor = fragColor + dstContribution; | |
347 } | |
348 break; | |
349 default: | |
350 SkFAIL("Unknown Primary Output"); | |
351 } | |
352 codeAppendf("\t%s = %s;\n", this->getColorOutputName(), fragColor.c_str()); | |
353 } | 345 } |
354 | |
355 const char* GrGLFragmentShaderBuilder::enableSecondaryOutput() { | |
356 if (!fHasSecondaryOutput) { | |
357 fOutputs.push_back().set(kVec4f_GrSLType, | |
358 GrGLShaderVar::kOut_TypeModifier, | |
359 dual_source_output_name()); | |
360 fHasSecondaryOutput = true; | |
361 } | |
362 return dual_source_output_name(); | |
363 } | |
364 | |
365 const char* GrGLFragmentShaderBuilder::getColorOutputName() const { | |
366 return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor"
; | |
367 } | |
368 | |
OLD | NEW |