1 /* 2 * Copyright 2011 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 "GrGLProgram.h" 9 10 #include "GrAllocator.h" 11 #include "GrEffect.h" 12 #include "GrCoordTransform.h" 13 #include "GrDrawEffect.h" 14 #include "GrGLEffect.h" 15 #include "GrGpuGL.h" 16 #include "GrGLShaderVar.h" 17 #include "GrGLSL.h" 18 #include "SkXfermode.h" 19 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) 22 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()) { 29 delete program; 30 program = NULL; 31 } 32 return program; 33 } 34 35 GrGLProgram::GrGLProgram(GrGpuGL* gpu, 36 const GrGLProgramDesc& desc, 37 const GrEffectStage* colorStages[], 38 const GrEffectStage* coverageStages[]) 39 : fGpu(gpu) 40 , fUniformManager(gpu) 41 , fHasVertexShader(false) 42 , fNumTexCoordSets(0) { 43 fDesc = desc; 44 fProgramID = 0; 45 46 fDstCopyTexUnit = -1; 47 48 fColor = GrColor_ILLEGAL; 49 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; 56 } 57 } else { 58 GrGLFragmentOnlyShaderBuilder fragmentOnlyBuilder(fGpu, fUniformManager, fDesc); 59 if (this->genProgram(&fragmentOnlyBuilder, colorStages, coverageStages)) { 60 fNumTexCoordSets = fragmentOnlyBuilder.getNumTexCoordSets(); 61 } 62 } 63 } 64 65 GrGLProgram::~GrGLProgram() { 66 if (fProgramID) { 67 GL_CALL(DeleteProgram(fProgramID)); 68 } 69 } 70 71 void GrGLProgram::abandon() { 72 fProgramID = 0; 73 } 74 75 void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff, 76 GrBlendCoeff* dstCoeff) const { 77 switch (fDesc.getHeader().fCoverageOutput) { 78 case GrGLProgramDesc::kModulate_CoverageOutput: 79 break; 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; 86 break; 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); 90 break; 91 default: 92 GrCrash("Unexpected coverage output"); 93 break; 94 } 95 } 96 97 bool GrGLProgram::genProgram(GrGLShaderBuilder* builder, 98 const GrEffectStage* colorStages[], 99 const GrEffectStage* coverageStages[]) { 100 SkASSERT(0 == fProgramID); 101 102 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); 103 104 // incoming color to current stage being processed. 105 GrGLSLExpr4 inColor = builder->getInputColor(); 106 107 fColorEffects.reset( 108 builder->createAndEmitEffects(colorStages, 109 fDesc.effectKeys(), 110 fDesc.numColorEffects(), 111 &inColor)); 112 113 /////////////////////////////////////////////////////////////////////////// 114 // compute the partial coverage 115 GrGLSLExpr4 inCoverage = builder->getInputCoverage(); 116 117 fCoverageEffects.reset( 118 builder->createAndEmitEffects(coverageStages, 119 fDesc.getEffectKeys() + fDesc.numColorEffects(), 120 fDesc.numCoverageEffects(), 121 &inCoverage)); 122 123 // discard if coverage is zero 124 if (header.fDiscardIfZeroCoverage && !inCoverage.isOnes()) { 125 if (inCoverage.isZeros()) { 126 // This is unfortunate. 127 builder->fsCodeAppend("\tdiscard;\n"); 128 } else { 129 builder->fsCodeAppendf("\tif (all(lessThanEqual(%s, vec4(0.0)))) {\n\t\tdiscard;\n\t}\n", 130 inCoverage.c_str()); 131 } 132 } 133 134 if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(header.fCoverageOutput)) { 135 const char* secondaryOutputName = builder->enableSecondaryOutput(); 136 137 // default coeff to ones for kCoverage_DualSrcOutput 138 GrGLSLExpr4 coeff(1); 139 if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCoverageOutput) { 140 // Get (1-A) into coeff 141 coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inColor.a()); 142 } else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput == header.fCoverageOutput) { 143 // Get (1-RGBA) into coeff 144 coeff = GrGLSLExpr4(1) - inColor; 145 } 146 // Get coeff * coverage into modulate and then write that to the dual source output. 147 builder->fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inCoverage).c_str()); 148 } 149 150 /////////////////////////////////////////////////////////////////////////// 151 // combine color and coverage as frag color 152 153 // Get "color * coverage" into fragColor 154 GrGLSLExpr4 fragColor = inColor * inCoverage; 155 // Now tack on "+(1-coverage)dst onto the frag color if we were asked to do so. 156 if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == header.fCoverageOutput) { 157 GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inCoverage; 158 159 GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(builder->dstColor()); 160 161 fragColor = fragColor + dstContribution; 162 } 163 builder->fsCodeAppendf("\t%s = %s;\n", builder->getColorOutputName(), fragColor.c_str()); 164 165 if (!builder->finish(&fProgramID)) { 166 return false; 167 } 168 169 fUniformHandles.fRTHeightUni = builder->getRTHeightUniform(); 170 fUniformHandles.fDstCopyTopLeftUni = builder->getDstCopyTopLeftUniform(); 171 fUniformHandles.fDstCopyScaleUni = builder->getDstCopyScaleUniform(); 172 fUniformHandles.fColorUni = builder->getColorUniform(); 173 fUniformHandles.fCoverageUni = builder->getCoverageUniform(); 174 fUniformHandles.fDstCopySamplerUni = builder->getDstCopySamplerUniform(); 175 // This must be called after we set fDstCopySamplerUni above. 176 this->initSamplerUniforms(); 177 178 return true; 179 } 180 181 void GrGLProgram::initSamplerUniforms() { 182 GL_CALL(UseProgram(fProgramID)); 183 GrGLint texUnitIdx = 0; 184 if (fUniformHandles.fDstCopySamplerUni.isValid()) { 185 fUniformManager.setSampler(fUniformHandles.fDstCopySamplerUni, texUnitIdx); 186 fDstCopyTexUnit = texUnitIdx++; 187 } 188 fColorEffects->initSamplers(fUniformManager, &texUnitIdx); 189 fCoverageEffects->initSamplers(fUniformManager, &texUnitIdx); 190 } 191 192 /////////////////////////////////////////////////////////////////////////////// 193 194 void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts, 195 const GrEffectStage* colorStages[], 196 const GrEffectStage* coverageStages[], 197 const GrDeviceCoordTexture* dstCopy, 198 SharedGLState* sharedState) { 199 const GrDrawState& drawState = fGpu->getDrawState(); 200 201 GrColor color; 202 GrColor coverage; 203 if (blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag) { 204 color = 0; 205 coverage = 0; 206 } else if (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) { 207 color = 0xffffffff; 208 coverage = drawState.getCoverageColor(); 209 } else { 210 color = drawState.getColor(); 211 coverage = drawState.getCoverageColor(); 212 } 213 214 this->setColor(drawState, color, sharedState); 215 this->setCoverage(drawState, coverage, sharedState); 216 this->setMatrixAndRenderTargetHeight(drawState); 217 218 if (NULL != dstCopy) { 219 if (fUniformHandles.fDstCopyTopLeftUni.isValid()) { 220 fUniformManager.set2f(fUniformHandles.fDstCopyTopLeftUni, 221 static_cast<GrGLfloat>(dstCopy->offset().fX), 222 static_cast<GrGLfloat>(dstCopy->offset().fY)); 223 fUniformManager.set2f(fUniformHandles.fDstCopyScaleUni, 224 1.f / dstCopy->texture()->width(), 225 1.f / dstCopy->texture()->height()); 226 GrGLTexture* texture = static_cast<GrGLTexture*>(dstCopy->texture()); 227 static GrTextureParams kParams; // the default is clamp, nearest filtering. 228 fGpu->bindTexture(fDstCopyTexUnit, kParams, texture); 229 } else { 230 SkASSERT(!fUniformHandles.fDstCopyScaleUni.isValid()); 231 SkASSERT(!fUniformHandles.fDstCopySamplerUni.isValid()); 232 } 233 } else { 234 SkASSERT(!fUniformHandles.fDstCopyTopLeftUni.isValid()); 235 SkASSERT(!fUniformHandles.fDstCopyScaleUni.isValid()); 236 SkASSERT(!fUniformHandles.fDstCopySamplerUni.isValid()); 237 } 238 239 fColorEffects->setData(fGpu, fUniformManager, colorStages); 240 fCoverageEffects->setData(fGpu, fUniformManager, coverageStages); 241 242 243 // TexGen state applies to the the fixed function vertex shader. For custom shaders, it's 244 // ignored, so we don't need to change the texgen settings in that case. 245 if (!fHasVertexShader) { 246 fGpu->flushTexGenSettings(fNumTexCoordSets); 247 } 248 } 249 250 void GrGLProgram::setColor(const GrDrawState& drawState, 251 GrColor color, 252 SharedGLState* sharedState) { 253 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); 254 if (!drawState.hasColorVertexAttribute()) { 255 switch (header.fColorInput) { 256 case GrGLProgramDesc::kAttribute_ColorInput: 257 SkASSERT(-1 != header.fColorAttributeIndex); 258 if (sharedState->fConstAttribColor != color || 259 sharedState->fConstAttribColorIndex != header.fColorAttributeIndex) { 260 // OpenGL ES only supports the float varieties of glVertexAttrib 261 GrGLfloat c[4]; 262 GrColorToRGBAFloat(color, c); 263 GL_CALL(VertexAttrib4fv(header.fColorAttributeIndex, c)); 264 sharedState->fConstAttribColor = color; 265 sharedState->fConstAttribColorIndex = header.fColorAttributeIndex; 266 } 267 break; 268 case GrGLProgramDesc::kUniform_ColorInput: 269 if (fColor != color && fUniformHandles.fColorUni.isValid()) { 270 // OpenGL ES doesn't support unsigned byte varieties of glUniform 271 GrGLfloat c[4]; 272 GrColorToRGBAFloat(color, c); 273 fUniformManager.set4fv(fUniformHandles.fColorUni, 1, c); 274 fColor = color; 275 } 276 sharedState->fConstAttribColorIndex = -1; 277 break; 278 case GrGLProgramDesc::kSolidWhite_ColorInput: 279 case GrGLProgramDesc::kTransBlack_ColorInput: 280 sharedState->fConstAttribColorIndex = -1; 281 break; 282 default: 283 GrCrash("Unknown color type."); 284 } 285 } else { 286 sharedState->fConstAttribColorIndex = -1; 287 } 288 } 289 290 void GrGLProgram::setCoverage(const GrDrawState& drawState, 291 GrColor coverage, 292 SharedGLState* sharedState) { 293 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); 294 if (!drawState.hasCoverageVertexAttribute()) { 295 switch (header.fCoverageInput) { 296 case GrGLProgramDesc::kAttribute_ColorInput: 297 if (sharedState->fConstAttribCoverage != coverage || 298 sharedState->fConstAttribCoverageIndex != header.fCoverageAttributeIndex) { 299 // OpenGL ES only supports the float varieties of glVertexAttrib 300 GrGLfloat c[4]; 301 GrColorToRGBAFloat(coverage, c); 302 GL_CALL(VertexAttrib4fv(header.fCoverageAttributeIndex, c)); 303 sharedState->fConstAttribCoverage = coverage; 304 sharedState->fConstAttribCoverageIndex = header.fCoverageAttributeIndex; 305 } 306 break; 307 case GrGLProgramDesc::kUniform_ColorInput: 308 if (fCoverage != coverage) { 309 // OpenGL ES doesn't support unsigned byte varieties of glUniform 310 GrGLfloat c[4]; 311 GrColorToRGBAFloat(coverage, c); 312 fUniformManager.set4fv(fUniformHandles.fCoverageUni, 1, c); 313 fCoverage = coverage; 314 } 315 sharedState->fConstAttribCoverageIndex = -1; 316 break; 317 case GrGLProgramDesc::kSolidWhite_ColorInput: 318 case GrGLProgramDesc::kTransBlack_ColorInput: 319 sharedState->fConstAttribCoverageIndex = -1; 320 break; 321 default: 322 GrCrash("Unknown coverage type."); 323 } 324 } else { 325 sharedState->fConstAttribCoverageIndex = -1; 326 } 327 } 328 329 void GrGLProgram::setMatrixAndRenderTargetHeight(const GrDrawState& drawState) { 330 const GrRenderTarget* rt = drawState.getRenderTarget(); 331 SkISize size; 332 size.set(rt->width(), rt->height()); 333 334 // Load the RT height uniform if it is needed to y-flip gl_FragCoord. 335 if (fUniformHandles.fRTHeightUni.isValid() && 336 fMatrixState.fRenderTargetSize.fHeight != size.fHeight) { 337 fUniformManager.set1f(fUniformHandles.fRTHeightUni, SkIntToScalar(size.fHeight)); 338 } 339 340 if (!fHasVertexShader) { 341 SkASSERT(!fUniformHandles.fViewMatrixUni.isValid()); 342 fGpu->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin()); 343 } else if (fMatrixState.fRenderTargetOrigin != rt->origin() || 344 fMatrixState.fRenderTargetSize != size || 345 !fMatrixState.fViewMatrix.cheapEqualTo(drawState.getViewMatrix())) { 346 SkASSERT(fUniformHandles.fViewMatrixUni.isValid()); 347 348 fMatrixState.fViewMatrix = drawState.getViewMatrix(); 349 fMatrixState.fRenderTargetSize = size; 350 fMatrixState.fRenderTargetOrigin = rt->origin(); 351 352 GrGLfloat viewMatrix[3 * 3]; 353 fMatrixState.getGLMatrix<3>(viewMatrix); 354 fUniformManager.setMatrix3f(fUniformHandles.fViewMatrixUni, viewMatrix); 355 } 356 } 357