2 * Copyright 2011 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "GrGLProgram.h"
10 #include "GrAllocator.h"
12 #include "GrCoordTransform.h"
13 #include "GrDrawEffect.h"
14 #include "GrGLEffect.h"
16 #include "GrGLShaderVar.h"
18 #include "SkXfermode.h"
20 #define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
21 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X)
23 GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu,
24 const GrGLProgramDesc& desc,
25 const GrEffectStage* colorStages[],
26 const GrEffectStage* coverageStages[]) {
27 GrGLProgram* program = SkNEW_ARGS(GrGLProgram, (gpu, desc, colorStages, coverageStages));
28 if (!program->succeeded()) {
35 GrGLProgram::GrGLProgram(GrGpuGL* gpu,
36 const GrGLProgramDesc& desc,
37 const GrEffectStage* colorStages[],
38 const GrEffectStage* coverageStages[])
40 , fUniformManager(gpu)
41 , fHasVertexShader(false)
42 , fNumTexCoordSets(0) {
48 fColor = GrColor_ILLEGAL;
50 if (fDesc.getHeader().fHasVertexCode ||
51 !fGpu->shouldUseFixedFunctionTexturing()) {
52 GrGLFullShaderBuilder fullBuilder(fGpu, fUniformManager, fDesc);
53 if (this->genProgram(&fullBuilder, colorStages, coverageStages)) {
54 fUniformHandles.fViewMatrixUni = fullBuilder.getViewMatrixUniform();
55 fHasVertexShader = true;
58 GrGLFragmentOnlyShaderBuilder fragmentOnlyBuilder(fGpu, fUniformManager, fDesc);
59 if (this->genProgram(&fragmentOnlyBuilder, colorStages, coverageStages)) {
60 fNumTexCoordSets = fragmentOnlyBuilder.getNumTexCoordSets();
65 GrGLProgram::~GrGLProgram() {
67 GL_CALL(DeleteProgram(fProgramID));
71 void GrGLProgram::abandon() {
75 void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff,
76 GrBlendCoeff* dstCoeff) const {
77 switch (fDesc.getHeader().fCoverageOutput) {
78 case GrGLProgramDesc::kModulate_CoverageOutput:
80 // The prog will write a coverage value to the secondary
81 // output and the dst is blended by one minus that value.
82 case GrGLProgramDesc::kSecondaryCoverage_CoverageOutput:
83 case GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput:
84 case GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput:
85 *dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
87 case GrGLProgramDesc::kCombineWithDst_CoverageOutput:
88 // We should only have set this if the blend was specified as (1, 0)
89 SkASSERT(kOne_GrBlendCoeff == *srcCoeff && kZero_GrBlendCoeff == *dstCoeff);
92 SkFAIL("Unexpected coverage output");
97 bool GrGLProgram::genProgram(GrGLShaderBuilder* builder,
98 const GrEffectStage* colorStages[],
99 const GrEffectStage* coverageStages[]) {
100 SkASSERT(0 == fProgramID);
102 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
104 // incoming color to current stage being processed.
105 GrGLSLExpr4 inColor = builder->getInputColor();
108 builder->createAndEmitEffects(colorStages,
110 fDesc.numColorEffects(),
113 ///////////////////////////////////////////////////////////////////////////
114 // compute the partial coverage
115 GrGLSLExpr4 inCoverage = builder->getInputCoverage();
117 fCoverageEffects.reset(
118 builder->createAndEmitEffects(coverageStages,
119 fDesc.getEffectKeys() + fDesc.numColorEffects(),
120 fDesc.numCoverageEffects(),
123 if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(header.fCoverageOutput)) {
124 const char* secondaryOutputName = builder->enableSecondaryOutput();
126 // default coeff to ones for kCoverage_DualSrcOutput
127 GrGLSLExpr4 coeff(1);
128 if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCoverageOutput) {
129 // Get (1-A) into coeff
130 coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inColor.a());
131 } else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput == header.fCoverageOutput) {
132 // Get (1-RGBA) into coeff
133 coeff = GrGLSLExpr4(1) - inColor;
135 // Get coeff * coverage into modulate and then write that to the dual source output.
136 builder->fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inCoverage).c_str());
139 ///////////////////////////////////////////////////////////////////////////
140 // combine color and coverage as frag color
142 // Get "color * coverage" into fragColor
143 GrGLSLExpr4 fragColor = inColor * inCoverage;
144 // Now tack on "+(1-coverage)dst onto the frag color if we were asked to do so.
145 if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == header.fCoverageOutput) {
146 GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inCoverage;
148 GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(builder->dstColor());
150 fragColor = fragColor + dstContribution;
152 builder->fsCodeAppendf("\t%s = %s;\n", builder->getColorOutputName(), fragColor.c_str());
154 if (!builder->finish(&fProgramID)) {
158 fUniformHandles.fRTHeightUni = builder->getRTHeightUniform();
159 fUniformHandles.fDstCopyTopLeftUni = builder->getDstCopyTopLeftUniform();
160 fUniformHandles.fDstCopyScaleUni = builder->getDstCopyScaleUniform();
161 fUniformHandles.fColorUni = builder->getColorUniform();
162 fUniformHandles.fCoverageUni = builder->getCoverageUniform();
163 fUniformHandles.fDstCopySamplerUni = builder->getDstCopySamplerUniform();
164 // This must be called after we set fDstCopySamplerUni above.
165 this->initSamplerUniforms();
170 void GrGLProgram::initSamplerUniforms() {
171 GL_CALL(UseProgram(fProgramID));
172 GrGLint texUnitIdx = 0;
173 if (fUniformHandles.fDstCopySamplerUni.isValid()) {
174 fUniformManager.setSampler(fUniformHandles.fDstCopySamplerUni, texUnitIdx);
175 fDstCopyTexUnit = texUnitIdx++;
177 fColorEffects->initSamplers(fUniformManager, &texUnitIdx);
178 fCoverageEffects->initSamplers(fUniformManager, &texUnitIdx);
181 ///////////////////////////////////////////////////////////////////////////////
183 void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts,
184 const GrEffectStage* colorStages[],
185 const GrEffectStage* coverageStages[],
186 const GrDeviceCoordTexture* dstCopy,
187 SharedGLState* sharedState) {
188 const GrDrawState& drawState = fGpu->getDrawState();
192 if (blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag) {
195 } else if (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) {
197 coverage = drawState.getCoverageColor();
199 color = drawState.getColor();
200 coverage = drawState.getCoverageColor();
203 this->setColor(drawState, color, sharedState);
204 this->setCoverage(drawState, coverage, sharedState);
205 this->setMatrixAndRenderTargetHeight(drawState);
207 if (NULL != dstCopy) {
208 if (fUniformHandles.fDstCopyTopLeftUni.isValid()) {
209 fUniformManager.set2f(fUniformHandles.fDstCopyTopLeftUni,
210 static_cast<GrGLfloat>(dstCopy->offset().fX),
211 static_cast<GrGLfloat>(dstCopy->offset().fY));
212 fUniformManager.set2f(fUniformHandles.fDstCopyScaleUni,
213 1.f / dstCopy->texture()->width(),
214 1.f / dstCopy->texture()->height());
215 GrGLTexture* texture = static_cast<GrGLTexture*>(dstCopy->texture());
216 static GrTextureParams kParams; // the default is clamp, nearest filtering.
217 fGpu->bindTexture(fDstCopyTexUnit, kParams, texture);
219 SkASSERT(!fUniformHandles.fDstCopyScaleUni.isValid());
220 SkASSERT(!fUniformHandles.fDstCopySamplerUni.isValid());
223 SkASSERT(!fUniformHandles.fDstCopyTopLeftUni.isValid());
224 SkASSERT(!fUniformHandles.fDstCopyScaleUni.isValid());
225 SkASSERT(!fUniformHandles.fDstCopySamplerUni.isValid());
228 fColorEffects->setData(fGpu, fUniformManager, colorStages);
229 fCoverageEffects->setData(fGpu, fUniformManager, coverageStages);
232 // PathTexGen state applies to the the fixed function vertex shader. For
233 // custom shaders, it's ignored, so we don't need to change the texgen
234 // settings in that case.
235 if (!fHasVertexShader) {
236 fGpu->flushPathTexGenSettings(fNumTexCoordSets);
240 void GrGLProgram::setColor(const GrDrawState& drawState,
242 SharedGLState* sharedState) {
243 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
244 if (!drawState.hasColorVertexAttribute()) {
245 switch (header.fColorInput) {
246 case GrGLProgramDesc::kAttribute_ColorInput:
247 SkASSERT(-1 != header.fColorAttributeIndex);
248 if (sharedState->fConstAttribColor != color ||
249 sharedState->fConstAttribColorIndex != header.fColorAttributeIndex) {
250 // OpenGL ES only supports the float varieties of glVertexAttrib
252 GrColorToRGBAFloat(color, c);
253 GL_CALL(VertexAttrib4fv(header.fColorAttributeIndex, c));
254 sharedState->fConstAttribColor = color;
255 sharedState->fConstAttribColorIndex = header.fColorAttributeIndex;
258 case GrGLProgramDesc::kUniform_ColorInput:
259 if (fColor != color && fUniformHandles.fColorUni.isValid()) {
260 // OpenGL ES doesn't support unsigned byte varieties of glUniform
262 GrColorToRGBAFloat(color, c);
263 fUniformManager.set4fv(fUniformHandles.fColorUni, 1, c);
266 sharedState->fConstAttribColorIndex = -1;
268 case GrGLProgramDesc::kSolidWhite_ColorInput:
269 case GrGLProgramDesc::kTransBlack_ColorInput:
270 sharedState->fConstAttribColorIndex = -1;
273 SkFAIL("Unknown color type.");
276 sharedState->fConstAttribColorIndex = -1;
280 void GrGLProgram::setCoverage(const GrDrawState& drawState,
282 SharedGLState* sharedState) {
283 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
284 if (!drawState.hasCoverageVertexAttribute()) {
285 switch (header.fCoverageInput) {
286 case GrGLProgramDesc::kAttribute_ColorInput:
287 if (sharedState->fConstAttribCoverage != coverage ||
288 sharedState->fConstAttribCoverageIndex != header.fCoverageAttributeIndex) {
289 // OpenGL ES only supports the float varieties of glVertexAttrib
291 GrColorToRGBAFloat(coverage, c);
292 GL_CALL(VertexAttrib4fv(header.fCoverageAttributeIndex, c));
293 sharedState->fConstAttribCoverage = coverage;
294 sharedState->fConstAttribCoverageIndex = header.fCoverageAttributeIndex;
297 case GrGLProgramDesc::kUniform_ColorInput:
298 if (fCoverage != coverage) {
299 // OpenGL ES doesn't support unsigned byte varieties of glUniform
301 GrColorToRGBAFloat(coverage, c);
302 fUniformManager.set4fv(fUniformHandles.fCoverageUni, 1, c);
303 fCoverage = coverage;
305 sharedState->fConstAttribCoverageIndex = -1;
307 case GrGLProgramDesc::kSolidWhite_ColorInput:
308 case GrGLProgramDesc::kTransBlack_ColorInput:
309 sharedState->fConstAttribCoverageIndex = -1;
312 SkFAIL("Unknown coverage type.");
315 sharedState->fConstAttribCoverageIndex = -1;
319 void GrGLProgram::setMatrixAndRenderTargetHeight(const GrDrawState& drawState) {
320 const GrRenderTarget* rt = drawState.getRenderTarget();
322 size.set(rt->width(), rt->height());
324 // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
325 if (fUniformHandles.fRTHeightUni.isValid() &&
326 fMatrixState.fRenderTargetSize.fHeight != size.fHeight) {
327 fUniformManager.set1f(fUniformHandles.fRTHeightUni, SkIntToScalar(size.fHeight));
330 if (!fHasVertexShader) {
331 SkASSERT(!fUniformHandles.fViewMatrixUni.isValid());
332 fGpu->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin());
333 } else if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
334 fMatrixState.fRenderTargetSize != size ||
335 !fMatrixState.fViewMatrix.cheapEqualTo(drawState.getViewMatrix())) {
336 SkASSERT(fUniformHandles.fViewMatrixUni.isValid());
338 fMatrixState.fViewMatrix = drawState.getViewMatrix();
339 fMatrixState.fRenderTargetSize = size;
340 fMatrixState.fRenderTargetOrigin = rt->origin();
342 GrGLfloat viewMatrix[3 * 3];
343 fMatrixState.getGLMatrix<3>(viewMatrix);
344 fUniformManager.setMatrix3f(fUniformHandles.fViewMatrixUni, viewMatrix);