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 GrGLShaderBuilder::GenProgramOutput output; 28 SkAutoTUnref<GrGLUniformManager> uman(SkNEW_ARGS(GrGLUniformManager, (gpu))); 29 if (GrGLShaderBuilder::GenProgram(gpu, uman, desc, colorStages, coverageStages, 30 &output)) { 31 SkASSERT(0 != output.fProgramID); 32 return SkNEW_ARGS(GrGLProgram, (gpu, desc, uman, output)); 33 } 34 return NULL; 35 } 36 37 GrGLProgram::GrGLProgram(GrGpuGL* gpu, 38 const GrGLProgramDesc& desc, 39 GrGLUniformManager* uman, 40 const GrGLShaderBuilder::GenProgramOutput& builderOutput) 41 : fColor(GrColor_ILLEGAL) 42 , fCoverage(GrColor_ILLEGAL) 43 , fDstCopyTexUnit(-1) 44 , fBuilderOutput(builderOutput) 45 , fDesc(desc) 46 , fGpu(gpu) 47 , fUniformManager(SkRef(uman)) { 48 this->initSamplerUniforms(); 49 } 50 51 GrGLProgram::~GrGLProgram() { 52 if (fBuilderOutput.fProgramID) { 53 GL_CALL(DeleteProgram(fBuilderOutput.fProgramID)); 54 } 55 } 56 57 void GrGLProgram::abandon() { 58 fBuilderOutput.fProgramID = 0; 59 } 60 61 void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff, 62 GrBlendCoeff* dstCoeff) const { 63 switch (fDesc.getHeader().fCoverageOutput) { 64 case GrGLProgramDesc::kModulate_CoverageOutput: 65 break; 66 // The prog will write a coverage value to the secondary 67 // output and the dst is blended by one minus that value. 68 case GrGLProgramDesc::kSecondaryCoverage_CoverageOutput: 69 case GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput: 70 case GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput: 71 *dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff; 72 break; 73 case GrGLProgramDesc::kCombineWithDst_CoverageOutput: 74 // We should only have set this if the blend was specified as (1, 0) 75 SkASSERT(kOne_GrBlendCoeff == *srcCoeff && kZero_GrBlendCoeff == *dstCoeff); 76 break; 77 default: 78 SkFAIL("Unexpected coverage output"); 79 break; 80 } 81 } 82 83 void GrGLProgram::initSamplerUniforms() { 84 GL_CALL(UseProgram(fBuilderOutput.fProgramID)); 85 GrGLint texUnitIdx = 0; 86 if (fBuilderOutput.fUniformHandles.fDstCopySamplerUni.isValid()) { 87 fUniformManager->setSampler(fBuilderOutput.fUniformHandles.fDstCopySamplerUni, texUnitIdx); 88 fDstCopyTexUnit = texUnitIdx++; 89 } 90 fBuilderOutput.fColorEffects->initSamplers(*fUniformManager, &texUnitIdx); 91 fBuilderOutput.fCoverageEffects->initSamplers(*fUniformManager, &texUnitIdx); 92 } 93 94 /////////////////////////////////////////////////////////////////////////////// 95 96 void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts, 97 const GrEffectStage* colorStages[], 98 const GrEffectStage* coverageStages[], 99 const GrDeviceCoordTexture* dstCopy, 100 SharedGLState* sharedState) { 101 const GrDrawState& drawState = fGpu->getDrawState(); 102 103 GrColor color; 104 GrColor coverage; 105 if (blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag) { 106 color = 0; 107 coverage = 0; 108 } else if (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) { 109 color = 0xffffffff; 110 coverage = drawState.getCoverageColor(); 111 } else { 112 color = drawState.getColor(); 113 coverage = drawState.getCoverageColor(); 114 } 115 116 this->setColor(drawState, color, sharedState); 117 this->setCoverage(drawState, coverage, sharedState); 118 this->setMatrixAndRenderTargetHeight(drawState); 119 120 if (NULL != dstCopy) { 121 if (fBuilderOutput.fUniformHandles.fDstCopyTopLeftUni.isValid()) { 122 fUniformManager->set2f(fBuilderOutput.fUniformHandles.fDstCopyTopLeftUni, 123 static_cast<GrGLfloat>(dstCopy->offset().fX), 124 static_cast<GrGLfloat>(dstCopy->offset().fY)); 125 fUniformManager->set2f(fBuilderOutput.fUniformHandles.fDstCopyScaleUni, 126 1.f / dstCopy->texture()->width(), 127 1.f / dstCopy->texture()->height()); 128 GrGLTexture* texture = static_cast<GrGLTexture*>(dstCopy->texture()); 129 static GrTextureParams kParams; // the default is clamp, nearest filtering. 130 fGpu->bindTexture(fDstCopyTexUnit, kParams, texture); 131 } else { 132 SkASSERT(!fBuilderOutput.fUniformHandles.fDstCopyScaleUni.isValid()); 133 SkASSERT(!fBuilderOutput.fUniformHandles.fDstCopySamplerUni.isValid()); 134 } 135 } else { 136 SkASSERT(!fBuilderOutput.fUniformHandles.fDstCopyTopLeftUni.isValid()); 137 SkASSERT(!fBuilderOutput.fUniformHandles.fDstCopyScaleUni.isValid()); 138 SkASSERT(!fBuilderOutput.fUniformHandles.fDstCopySamplerUni.isValid()); 139 } 140 141 fBuilderOutput.fColorEffects->setData(fGpu, *fUniformManager, colorStages); 142 fBuilderOutput.fCoverageEffects->setData(fGpu, *fUniformManager, coverageStages); 143 144 145 // PathTexGen state applies to the the fixed function vertex shader. For 146 // custom shaders, it's ignored, so we don't need to change the texgen 147 // settings in that case. 148 if (!fBuilderOutput.fHasVertexShader) { 149 fGpu->flushPathTexGenSettings(fBuilderOutput.fTexCoordSetCnt); 150 } 151 } 152 153 void GrGLProgram::setColor(const GrDrawState& drawState, 154 GrColor color, 155 SharedGLState* sharedState) { 156 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); 157 if (!drawState.hasColorVertexAttribute()) { 158 switch (header.fColorInput) { 159 case GrGLProgramDesc::kAttribute_ColorInput: 160 SkASSERT(-1 != header.fColorAttributeIndex); 161 if (sharedState->fConstAttribColor != color || 162 sharedState->fConstAttribColorIndex != header.fColorAttributeIndex) { 163 // OpenGL ES only supports the float varieties of glVertexAttrib 164 GrGLfloat c[4]; 165 GrColorToRGBAFloat(color, c); 166 GL_CALL(VertexAttrib4fv(header.fColorAttributeIndex, c)); 167 sharedState->fConstAttribColor = color; 168 sharedState->fConstAttribColorIndex = header.fColorAttributeIndex; 169 } 170 break; 171 case GrGLProgramDesc::kUniform_ColorInput: 172 if (fColor != color && fBuilderOutput.fUniformHandles.fColorUni.isValid()) { 173 // OpenGL ES doesn't support unsigned byte varieties of glUniform 174 GrGLfloat c[4]; 175 GrColorToRGBAFloat(color, c); 176 fUniformManager->set4fv(fBuilderOutput.fUniformHandles.fColorUni, 1, c); 177 fColor = color; 178 } 179 sharedState->fConstAttribColorIndex = -1; 180 break; 181 case GrGLProgramDesc::kSolidWhite_ColorInput: 182 case GrGLProgramDesc::kTransBlack_ColorInput: 183 sharedState->fConstAttribColorIndex = -1; 184 break; 185 default: 186 SkFAIL("Unknown color type."); 187 } 188 } else { 189 sharedState->fConstAttribColorIndex = -1; 190 } 191 } 192 193 void GrGLProgram::setCoverage(const GrDrawState& drawState, 194 GrColor coverage, 195 SharedGLState* sharedState) { 196 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); 197 if (!drawState.hasCoverageVertexAttribute()) { 198 switch (header.fCoverageInput) { 199 case GrGLProgramDesc::kAttribute_ColorInput: 200 if (sharedState->fConstAttribCoverage != coverage || 201 sharedState->fConstAttribCoverageIndex != header.fCoverageAttributeIndex) { 202 // OpenGL ES only supports the float varieties of glVertexAttrib 203 GrGLfloat c[4]; 204 GrColorToRGBAFloat(coverage, c); 205 GL_CALL(VertexAttrib4fv(header.fCoverageAttributeIndex, c)); 206 sharedState->fConstAttribCoverage = coverage; 207 sharedState->fConstAttribCoverageIndex = header.fCoverageAttributeIndex; 208 } 209 break; 210 case GrGLProgramDesc::kUniform_ColorInput: 211 if (fCoverage != coverage) { 212 // OpenGL ES doesn't support unsigned byte varieties of glUniform 213 GrGLfloat c[4]; 214 GrColorToRGBAFloat(coverage, c); 215 fUniformManager->set4fv(fBuilderOutput.fUniformHandles.fCoverageUni, 1, c); 216 fCoverage = coverage; 217 } 218 sharedState->fConstAttribCoverageIndex = -1; 219 break; 220 case GrGLProgramDesc::kSolidWhite_ColorInput: 221 case GrGLProgramDesc::kTransBlack_ColorInput: 222 sharedState->fConstAttribCoverageIndex = -1; 223 break; 224 default: 225 SkFAIL("Unknown coverage type."); 226 } 227 } else { 228 sharedState->fConstAttribCoverageIndex = -1; 229 } 230 } 231 232 void GrGLProgram::setMatrixAndRenderTargetHeight(const GrDrawState& drawState) { 233 const GrRenderTarget* rt = drawState.getRenderTarget(); 234 SkISize size; 235 size.set(rt->width(), rt->height()); 236 237 // Load the RT height uniform if it is needed to y-flip gl_FragCoord. 238 if (fBuilderOutput.fUniformHandles.fRTHeightUni.isValid() && 239 fMatrixState.fRenderTargetSize.fHeight != size.fHeight) { 240 fUniformManager->set1f(fBuilderOutput.fUniformHandles.fRTHeightUni, 241 SkIntToScalar(size.fHeight)); 242 } 243 244 if (!fBuilderOutput.fHasVertexShader) { 245 SkASSERT(!fBuilderOutput.fUniformHandles.fViewMatrixUni.isValid()); 246 SkASSERT(!fBuilderOutput.fUniformHandles.fRTAdjustmentUni.isValid()); 247 fGpu->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin()); 248 } else if (fMatrixState.fRenderTargetOrigin != rt->origin() || 249 fMatrixState.fRenderTargetSize != size || 250 !fMatrixState.fViewMatrix.cheapEqualTo(drawState.getViewMatrix())) { 251 SkASSERT(fBuilderOutput.fUniformHandles.fViewMatrixUni.isValid()); 252 253 fMatrixState.fViewMatrix = drawState.getViewMatrix(); 254 fMatrixState.fRenderTargetSize = size; 255 fMatrixState.fRenderTargetOrigin = rt->origin(); 256 257 GrGLfloat viewMatrix[3 * 3]; 258 fMatrixState.getGLMatrix<3>(viewMatrix); 259 fUniformManager->setMatrix3f(fBuilderOutput.fUniformHandles.fViewMatrixUni, viewMatrix); 260 261 GrGLfloat rtAdjustmentVec[4]; 262 fMatrixState.getRTAdjustmentVec(rtAdjustmentVec); 263 fUniformManager->set4fv(fBuilderOutput.fUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec); 264 } 265 } 266