OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 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 "GrGLProgram.h" | 8 #include "GrGLProgram.h" |
9 | 9 |
10 #include "GrAllocator.h" | 10 #include "GrAllocator.h" |
(...skipping 30 matching lines...) Expand all Loading... |
41 : fGpu(gpu) | 41 : fGpu(gpu) |
42 , fUniformManager(gpu) | 42 , fUniformManager(gpu) |
43 , fHasVertexShader(false) | 43 , fHasVertexShader(false) |
44 , fNumTexCoordSets(0) { | 44 , fNumTexCoordSets(0) { |
45 fDesc = desc; | 45 fDesc = desc; |
46 fProgramID = 0; | 46 fProgramID = 0; |
47 | 47 |
48 fDstCopyTexUnit = -1; | 48 fDstCopyTexUnit = -1; |
49 | 49 |
50 fColor = GrColor_ILLEGAL; | 50 fColor = GrColor_ILLEGAL; |
51 fColorFilterColor = GrColor_ILLEGAL; | |
52 | 51 |
53 if (fDesc.getHeader().fHasVertexCode || | 52 if (fDesc.getHeader().fHasVertexCode || |
54 !fGpu->shouldUseFixedFunctionTexturing()) { | 53 !fGpu->shouldUseFixedFunctionTexturing()) { |
55 GrGLFullShaderBuilder fullBuilder(fGpu, fUniformManager, fDesc); | 54 GrGLFullShaderBuilder fullBuilder(fGpu, fUniformManager, fDesc); |
56 if (this->genProgram(&fullBuilder, colorStages, coverageStages)) { | 55 if (this->genProgram(&fullBuilder, colorStages, coverageStages)) { |
57 fUniformHandles.fViewMatrixUni = fullBuilder.getViewMatrixUniform(); | 56 fUniformHandles.fViewMatrixUni = fullBuilder.getViewMatrixUniform(); |
58 fHasVertexShader = true; | 57 fHasVertexShader = true; |
59 } | 58 } |
60 } else { | 59 } else { |
61 GrGLFragmentOnlyShaderBuilder fragmentOnlyBuilder(fGpu, fUniformManager,
fDesc); | 60 GrGLFragmentOnlyShaderBuilder fragmentOnlyBuilder(fGpu, fUniformManager,
fDesc); |
(...skipping 28 matching lines...) Expand all Loading... |
90 case GrGLProgramDesc::kCombineWithDst_CoverageOutput: | 89 case GrGLProgramDesc::kCombineWithDst_CoverageOutput: |
91 // We should only have set this if the blend was specified as (1, 0) | 90 // We should only have set this if the blend was specified as (1, 0) |
92 SkASSERT(kOne_GrBlendCoeff == *srcCoeff && kZero_GrBlendCoeff == *ds
tCoeff); | 91 SkASSERT(kOne_GrBlendCoeff == *srcCoeff && kZero_GrBlendCoeff == *ds
tCoeff); |
93 break; | 92 break; |
94 default: | 93 default: |
95 GrCrash("Unexpected coverage output"); | 94 GrCrash("Unexpected coverage output"); |
96 break; | 95 break; |
97 } | 96 } |
98 } | 97 } |
99 | 98 |
100 namespace { | |
101 // given two blend coefficients determine whether the src | |
102 // and/or dst computation can be omitted. | |
103 inline void need_blend_inputs(SkXfermode::Coeff srcCoeff, | |
104 SkXfermode::Coeff dstCoeff, | |
105 bool* needSrcValue, | |
106 bool* needDstValue) { | |
107 if (SkXfermode::kZero_Coeff == srcCoeff) { | |
108 switch (dstCoeff) { | |
109 // these all read the src | |
110 case SkXfermode::kSC_Coeff: | |
111 case SkXfermode::kISC_Coeff: | |
112 case SkXfermode::kSA_Coeff: | |
113 case SkXfermode::kISA_Coeff: | |
114 *needSrcValue = true; | |
115 break; | |
116 default: | |
117 *needSrcValue = false; | |
118 break; | |
119 } | |
120 } else { | |
121 *needSrcValue = true; | |
122 } | |
123 if (SkXfermode::kZero_Coeff == dstCoeff) { | |
124 switch (srcCoeff) { | |
125 // these all read the dst | |
126 case SkXfermode::kDC_Coeff: | |
127 case SkXfermode::kIDC_Coeff: | |
128 case SkXfermode::kDA_Coeff: | |
129 case SkXfermode::kIDA_Coeff: | |
130 *needDstValue = true; | |
131 break; | |
132 default: | |
133 *needDstValue = false; | |
134 break; | |
135 } | |
136 } else { | |
137 *needDstValue = true; | |
138 } | |
139 } | |
140 | |
141 /** | |
142 * Create a blend_coeff * value string to be used in shader code. Sets empty | |
143 * string if result is trivially zero. | |
144 */ | |
145 inline void blend_term_string(SkString* str, SkXfermode::Coeff coeff, | |
146 const char* src, const char* dst, | |
147 const char* value) { | |
148 switch (coeff) { | |
149 case SkXfermode::kZero_Coeff: /** 0 */ | |
150 *str = ""; | |
151 break; | |
152 case SkXfermode::kOne_Coeff: /** 1 */ | |
153 *str = value; | |
154 break; | |
155 case SkXfermode::kSC_Coeff: | |
156 str->printf("(%s * %s)", src, value); | |
157 break; | |
158 case SkXfermode::kISC_Coeff: | |
159 str->printf("((vec4(1) - %s) * %s)", src, value); | |
160 break; | |
161 case SkXfermode::kDC_Coeff: | |
162 str->printf("(%s * %s)", dst, value); | |
163 break; | |
164 case SkXfermode::kIDC_Coeff: | |
165 str->printf("((vec4(1) - %s) * %s)", dst, value); | |
166 break; | |
167 case SkXfermode::kSA_Coeff: /** src alpha */ | |
168 str->printf("(%s.a * %s)", src, value); | |
169 break; | |
170 case SkXfermode::kISA_Coeff: /** inverse src alpha (i.e. 1 - sa) */ | |
171 str->printf("((1.0 - %s.a) * %s)", src, value); | |
172 break; | |
173 case SkXfermode::kDA_Coeff: /** dst alpha */ | |
174 str->printf("(%s.a * %s)", dst, value); | |
175 break; | |
176 case SkXfermode::kIDA_Coeff: /** inverse dst alpha (i.e. 1 - da) */ | |
177 str->printf("((1.0 - %s.a) * %s)", dst, value); | |
178 break; | |
179 default: | |
180 GrCrash("Unexpected xfer coeff."); | |
181 break; | |
182 } | |
183 } | |
184 /** | |
185 * Adds a line to the fragment shader code which modifies the color by | |
186 * the specified color filter. | |
187 */ | |
188 void add_color_filter(GrGLShaderBuilder* builder, | |
189 const char * outputVar, | |
190 SkXfermode::Coeff uniformCoeff, | |
191 SkXfermode::Coeff colorCoeff, | |
192 const char* filterColor, | |
193 const char* inColor) { | |
194 SkString colorStr, constStr; | |
195 blend_term_string(&colorStr, colorCoeff, filterColor, inColor, inColor); | |
196 blend_term_string(&constStr, uniformCoeff, filterColor, inColor, filterColor
); | |
197 GrGLSLExpr<4> sum; | |
198 if (colorStr.isEmpty() && constStr.isEmpty()) { | |
199 sum = GrGLSLExpr<4>(0); | |
200 } else if (colorStr.isEmpty()) { | |
201 sum = constStr; | |
202 } else if (constStr.isEmpty()) { | |
203 sum = colorStr; | |
204 } else { | |
205 sum = GrGLSLExpr<4>(colorStr) + GrGLSLExpr<4>(constStr); | |
206 } | |
207 builder->fsCodeAppendf("\t%s = %s;\n", outputVar, sum.c_str()); | |
208 } | |
209 } | |
210 | |
211 bool GrGLProgram::genProgram(GrGLShaderBuilder* builder, | 99 bool GrGLProgram::genProgram(GrGLShaderBuilder* builder, |
212 const GrEffectStage* colorStages[], | 100 const GrEffectStage* colorStages[], |
213 const GrEffectStage* coverageStages[]) { | 101 const GrEffectStage* coverageStages[]) { |
214 SkASSERT(0 == fProgramID); | 102 SkASSERT(0 == fProgramID); |
215 | 103 |
216 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); | 104 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); |
217 | 105 |
218 // incoming color to current stage being processed. | 106 // incoming color to current stage being processed. |
219 GrGLSLExpr<4> inColor = builder->getInputColor(); | 107 GrGLSLExpr4 inColor = builder->getInputColor(); |
220 | |
221 // Get the coeffs for the Mode-based color filter, determine if color is nee
ded. | |
222 SkXfermode::Coeff colorCoeff; | |
223 SkXfermode::Coeff filterColorCoeff; | |
224 SkAssertResult( | |
225 SkXfermode::ModeAsCoeff(header.fColorFilterXfermode, | |
226 &filterColorCoeff, | |
227 &colorCoeff)); | |
228 bool needColor, needFilterColor; | |
229 need_blend_inputs(filterColorCoeff, colorCoeff, &needFilterColor, &needColor
); | |
230 | 108 |
231 fColorEffects.reset( | 109 fColorEffects.reset( |
232 builder->createAndEmitEffects(colorStages, | 110 builder->createAndEmitEffects(colorStages, |
233 fDesc.effectKeys(), | 111 fDesc.effectKeys(), |
234 needColor ? fDesc.numColorEffects() : 0, | 112 fDesc.numColorEffects(), |
235 &inColor)); | 113 &inColor)); |
236 | 114 |
237 // Insert the color filter. This will soon be replaced by a color effect. | |
238 if (SkXfermode::kDst_Mode != header.fColorFilterXfermode) { | |
239 const char* colorFilterColorUniName = NULL; | |
240 fUniformHandles.fColorFilterUni = builder->addUniform(GrGLShaderBuilder:
:kFragment_Visibility, | |
241 kVec4f_GrSLType, "
FilterColor", | |
242 &colorFilterColorU
niName); | |
243 | |
244 builder->fsCodeAppend("\tvec4 filteredColor;\n"); | |
245 add_color_filter(builder, "filteredColor", filterColorCoeff, | |
246 colorCoeff, colorFilterColorUniName, inColor.c_str()); | |
247 inColor = "filteredColor"; | |
248 } | |
249 | |
250 /////////////////////////////////////////////////////////////////////////// | 115 /////////////////////////////////////////////////////////////////////////// |
251 // compute the partial coverage | 116 // compute the partial coverage |
252 GrGLSLExpr<4> inCoverage = builder->getInputCoverage(); | 117 GrGLSLExpr4 inCoverage = builder->getInputCoverage(); |
253 | 118 |
254 fCoverageEffects.reset( | 119 fCoverageEffects.reset( |
255 builder->createAndEmitEffects(coverageStages, | 120 builder->createAndEmitEffects(coverageStages, |
256 fDesc.getEffectKeys() + fDesc.numColorEffe
cts(), | 121 fDesc.getEffectKeys() + fDesc.numColorEffe
cts(), |
257 fDesc.numCoverageEffects(), | 122 fDesc.numCoverageEffects(), |
258 &inCoverage)); | 123 &inCoverage)); |
259 | 124 |
260 // discard if coverage is zero | 125 // discard if coverage is zero |
261 if (header.fDiscardIfZeroCoverage && !inCoverage.isOnes()) { | 126 if (header.fDiscardIfZeroCoverage && !inCoverage.isOnes()) { |
262 if (inCoverage.isZeros()) { | 127 if (inCoverage.isZeros()) { |
263 // This is unfortunate. | 128 // This is unfortunate. |
264 builder->fsCodeAppend("\tdiscard;\n"); | 129 builder->fsCodeAppend("\tdiscard;\n"); |
265 } else { | 130 } else { |
266 builder->fsCodeAppendf("\tif (all(lessThanEqual(%s, vec4(0.0)))) {\n
\t\tdiscard;\n\t}\n", | 131 builder->fsCodeAppendf("\tif (all(lessThanEqual(%s, vec4(0.0)))) {\n
\t\tdiscard;\n\t}\n", |
267 inCoverage.c_str()); | 132 inCoverage.c_str()); |
268 } | 133 } |
269 } | 134 } |
270 | 135 |
271 if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(header.fCoverageOutpu
t)) { | 136 if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(header.fCoverageOutpu
t)) { |
272 const char* secondaryOutputName = builder->enableSecondaryOutput(); | 137 const char* secondaryOutputName = builder->enableSecondaryOutput(); |
273 | 138 |
274 // default coeff to ones for kCoverage_DualSrcOutput | 139 // default coeff to ones for kCoverage_DualSrcOutput |
275 GrGLSLExpr<4> coeff(1); | 140 GrGLSLExpr4 coeff(1); |
276 if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCov
erageOutput) { | 141 if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCov
erageOutput) { |
277 // Get (1-A) into coeff | 142 // Get (1-A) into coeff |
278 coeff = GrGLSLExprCast4(GrGLSLExpr<1>(1) - GrGLSLExprExtractAlpha(in
Color)); | 143 coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inColor.a()); |
279 } else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput == head
er.fCoverageOutput) { | 144 } else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput == head
er.fCoverageOutput) { |
280 // Get (1-RGBA) into coeff | 145 // Get (1-RGBA) into coeff |
281 coeff = GrGLSLExpr<4>(1) - inColor; | 146 coeff = GrGLSLExpr4(1) - inColor; |
282 } | 147 } |
283 // Get coeff * coverage into modulate and then write that to the dual so
urce output. | 148 // Get coeff * coverage into modulate and then write that to the dual so
urce output. |
284 builder->fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inC
overage).c_str()); | 149 builder->fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inC
overage).c_str()); |
285 } | 150 } |
286 | 151 |
287 /////////////////////////////////////////////////////////////////////////// | 152 /////////////////////////////////////////////////////////////////////////// |
288 // combine color and coverage as frag color | 153 // combine color and coverage as frag color |
289 | 154 |
290 // Get "color * coverage" into fragColor | 155 // Get "color * coverage" into fragColor |
291 GrGLSLExpr<4> fragColor = inColor * inCoverage; | 156 GrGLSLExpr4 fragColor = inColor * inCoverage; |
292 // Now tack on "+(1-coverage)dst onto the frag color if we were asked to do
so. | 157 // Now tack on "+(1-coverage)dst onto the frag color if we were asked to do
so. |
293 if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == header.fCoverageOutpu
t) { | 158 if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == header.fCoverageOutpu
t) { |
294 GrGLSLExpr<4> dstCoeff = GrGLSLExpr<4>(1) - inCoverage; | 159 GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inCoverage; |
295 | 160 |
296 GrGLSLExpr<4> dstContribution = dstCoeff * GrGLSLExpr<4>(builder->dstCol
or()); | 161 GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(builder->dstColor()
); |
297 | 162 |
298 fragColor = fragColor + dstContribution; | 163 fragColor = fragColor + dstContribution; |
299 } | 164 } |
300 builder->fsCodeAppendf("\t%s = %s;\n", builder->getColorOutputName(), fragCo
lor.c_str()); | 165 builder->fsCodeAppendf("\t%s = %s;\n", builder->getColorOutputName(), fragCo
lor.c_str()); |
301 | 166 |
302 if (!builder->finish(&fProgramID)) { | 167 if (!builder->finish(&fProgramID)) { |
303 return false; | 168 return false; |
304 } | 169 } |
305 | 170 |
306 fUniformHandles.fRTHeightUni = builder->getRTHeightUniform(); | 171 fUniformHandles.fRTHeightUni = builder->getRTHeightUniform(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
345 coverage = drawState.getCoverage(); | 210 coverage = drawState.getCoverage(); |
346 } else { | 211 } else { |
347 color = drawState.getColor(); | 212 color = drawState.getColor(); |
348 coverage = drawState.getCoverage(); | 213 coverage = drawState.getCoverage(); |
349 } | 214 } |
350 | 215 |
351 this->setColor(drawState, color, sharedState); | 216 this->setColor(drawState, color, sharedState); |
352 this->setCoverage(drawState, coverage, sharedState); | 217 this->setCoverage(drawState, coverage, sharedState); |
353 this->setMatrixAndRenderTargetHeight(drawState); | 218 this->setMatrixAndRenderTargetHeight(drawState); |
354 | 219 |
355 // Setup the SkXfermode::Mode-based colorfilter uniform if necessary | |
356 if (fUniformHandles.fColorFilterUni.isValid() && | |
357 fColorFilterColor != drawState.getColorFilterColor()) { | |
358 GrGLfloat c[4]; | |
359 GrColorToRGBAFloat(drawState.getColorFilterColor(), c); | |
360 fUniformManager.set4fv(fUniformHandles.fColorFilterUni, 0, 1, c); | |
361 fColorFilterColor = drawState.getColorFilterColor(); | |
362 } | |
363 | |
364 if (NULL != dstCopy) { | 220 if (NULL != dstCopy) { |
365 if (fUniformHandles.fDstCopyTopLeftUni.isValid()) { | 221 if (fUniformHandles.fDstCopyTopLeftUni.isValid()) { |
366 fUniformManager.set2f(fUniformHandles.fDstCopyTopLeftUni, | 222 fUniformManager.set2f(fUniformHandles.fDstCopyTopLeftUni, |
367 static_cast<GrGLfloat>(dstCopy->offset().fX), | 223 static_cast<GrGLfloat>(dstCopy->offset().fX), |
368 static_cast<GrGLfloat>(dstCopy->offset().fY)); | 224 static_cast<GrGLfloat>(dstCopy->offset().fY)); |
369 fUniformManager.set2f(fUniformHandles.fDstCopyScaleUni, | 225 fUniformManager.set2f(fUniformHandles.fDstCopyScaleUni, |
370 1.f / dstCopy->texture()->width(), | 226 1.f / dstCopy->texture()->width(), |
371 1.f / dstCopy->texture()->height()); | 227 1.f / dstCopy->texture()->height()); |
372 GrGLTexture* texture = static_cast<GrGLTexture*>(dstCopy->texture())
; | 228 GrGLTexture* texture = static_cast<GrGLTexture*>(dstCopy->texture())
; |
373 static GrTextureParams kParams; // the default is clamp, nearest fil
tering. | 229 static GrTextureParams kParams; // the default is clamp, nearest fil
tering. |
(...skipping 28 matching lines...) Expand all Loading... |
402 sharedState->fConstAttribColorIndex != header.fColorAttribut
eIndex) { | 258 sharedState->fConstAttribColorIndex != header.fColorAttribut
eIndex) { |
403 // OpenGL ES only supports the float varieties of glVertexAt
trib | 259 // OpenGL ES only supports the float varieties of glVertexAt
trib |
404 GrGLfloat c[4]; | 260 GrGLfloat c[4]; |
405 GrColorToRGBAFloat(color, c); | 261 GrColorToRGBAFloat(color, c); |
406 GL_CALL(VertexAttrib4fv(header.fColorAttributeIndex, c)); | 262 GL_CALL(VertexAttrib4fv(header.fColorAttributeIndex, c)); |
407 sharedState->fConstAttribColor = color; | 263 sharedState->fConstAttribColor = color; |
408 sharedState->fConstAttribColorIndex = header.fColorAttribute
Index; | 264 sharedState->fConstAttribColorIndex = header.fColorAttribute
Index; |
409 } | 265 } |
410 break; | 266 break; |
411 case GrGLProgramDesc::kUniform_ColorInput: | 267 case GrGLProgramDesc::kUniform_ColorInput: |
412 if (fColor != color) { | 268 if (fColor != color && fUniformHandles.fColorUni.isValid()) { |
413 // OpenGL ES doesn't support unsigned byte varieties of glUn
iform | 269 // OpenGL ES doesn't support unsigned byte varieties of glUn
iform |
414 GrGLfloat c[4]; | 270 GrGLfloat c[4]; |
415 GrColorToRGBAFloat(color, c); | 271 GrColorToRGBAFloat(color, c); |
416 fUniformManager.set4fv(fUniformHandles.fColorUni, 0, 1, c); | 272 fUniformManager.set4fv(fUniformHandles.fColorUni, 0, 1, c); |
417 fColor = color; | 273 fColor = color; |
418 } | 274 } |
419 sharedState->fConstAttribColorIndex = -1; | 275 sharedState->fConstAttribColorIndex = -1; |
420 break; | 276 break; |
421 case GrGLProgramDesc::kSolidWhite_ColorInput: | 277 case GrGLProgramDesc::kSolidWhite_ColorInput: |
422 case GrGLProgramDesc::kTransBlack_ColorInput: | 278 case GrGLProgramDesc::kTransBlack_ColorInput: |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
490 | 346 |
491 fMatrixState.fViewMatrix = drawState.getViewMatrix(); | 347 fMatrixState.fViewMatrix = drawState.getViewMatrix(); |
492 fMatrixState.fRenderTargetSize = size; | 348 fMatrixState.fRenderTargetSize = size; |
493 fMatrixState.fRenderTargetOrigin = rt->origin(); | 349 fMatrixState.fRenderTargetOrigin = rt->origin(); |
494 | 350 |
495 GrGLfloat viewMatrix[3 * 3]; | 351 GrGLfloat viewMatrix[3 * 3]; |
496 fMatrixState.getGLMatrix<3>(viewMatrix); | 352 fMatrixState.getGLMatrix<3>(viewMatrix); |
497 fUniformManager.setMatrix3f(fUniformHandles.fViewMatrixUni, viewMatrix); | 353 fUniformManager.setMatrix3f(fUniformHandles.fViewMatrixUni, viewMatrix); |
498 } | 354 } |
499 } | 355 } |
OLD | NEW |