1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/gpu/gl/GrGLProgram.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,345 @@ 1.4 +/* 1.5 + * Copyright 2011 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#include "GrGLProgram.h" 1.12 + 1.13 +#include "GrAllocator.h" 1.14 +#include "GrEffect.h" 1.15 +#include "GrCoordTransform.h" 1.16 +#include "GrDrawEffect.h" 1.17 +#include "GrGLEffect.h" 1.18 +#include "GrGpuGL.h" 1.19 +#include "GrGLShaderVar.h" 1.20 +#include "GrGLSL.h" 1.21 +#include "SkXfermode.h" 1.22 + 1.23 +#define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X) 1.24 +#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X) 1.25 + 1.26 +GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu, 1.27 + const GrGLProgramDesc& desc, 1.28 + const GrEffectStage* colorStages[], 1.29 + const GrEffectStage* coverageStages[]) { 1.30 + GrGLProgram* program = SkNEW_ARGS(GrGLProgram, (gpu, desc, colorStages, coverageStages)); 1.31 + if (!program->succeeded()) { 1.32 + delete program; 1.33 + program = NULL; 1.34 + } 1.35 + return program; 1.36 +} 1.37 + 1.38 +GrGLProgram::GrGLProgram(GrGpuGL* gpu, 1.39 + const GrGLProgramDesc& desc, 1.40 + const GrEffectStage* colorStages[], 1.41 + const GrEffectStage* coverageStages[]) 1.42 +: fGpu(gpu) 1.43 +, fUniformManager(gpu) 1.44 +, fHasVertexShader(false) 1.45 +, fNumTexCoordSets(0) { 1.46 + fDesc = desc; 1.47 + fProgramID = 0; 1.48 + 1.49 + fDstCopyTexUnit = -1; 1.50 + 1.51 + fColor = GrColor_ILLEGAL; 1.52 + 1.53 + if (fDesc.getHeader().fHasVertexCode || 1.54 + !fGpu->shouldUseFixedFunctionTexturing()) { 1.55 + GrGLFullShaderBuilder fullBuilder(fGpu, fUniformManager, fDesc); 1.56 + if (this->genProgram(&fullBuilder, colorStages, coverageStages)) { 1.57 + fUniformHandles.fViewMatrixUni = fullBuilder.getViewMatrixUniform(); 1.58 + fHasVertexShader = true; 1.59 + } 1.60 + } else { 1.61 + GrGLFragmentOnlyShaderBuilder fragmentOnlyBuilder(fGpu, fUniformManager, fDesc); 1.62 + if (this->genProgram(&fragmentOnlyBuilder, colorStages, coverageStages)) { 1.63 + fNumTexCoordSets = fragmentOnlyBuilder.getNumTexCoordSets(); 1.64 + } 1.65 + } 1.66 +} 1.67 + 1.68 +GrGLProgram::~GrGLProgram() { 1.69 + if (fProgramID) { 1.70 + GL_CALL(DeleteProgram(fProgramID)); 1.71 + } 1.72 +} 1.73 + 1.74 +void GrGLProgram::abandon() { 1.75 + fProgramID = 0; 1.76 +} 1.77 + 1.78 +void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff, 1.79 + GrBlendCoeff* dstCoeff) const { 1.80 + switch (fDesc.getHeader().fCoverageOutput) { 1.81 + case GrGLProgramDesc::kModulate_CoverageOutput: 1.82 + break; 1.83 + // The prog will write a coverage value to the secondary 1.84 + // output and the dst is blended by one minus that value. 1.85 + case GrGLProgramDesc::kSecondaryCoverage_CoverageOutput: 1.86 + case GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput: 1.87 + case GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput: 1.88 + *dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff; 1.89 + break; 1.90 + case GrGLProgramDesc::kCombineWithDst_CoverageOutput: 1.91 + // We should only have set this if the blend was specified as (1, 0) 1.92 + SkASSERT(kOne_GrBlendCoeff == *srcCoeff && kZero_GrBlendCoeff == *dstCoeff); 1.93 + break; 1.94 + default: 1.95 + GrCrash("Unexpected coverage output"); 1.96 + break; 1.97 + } 1.98 +} 1.99 + 1.100 +bool GrGLProgram::genProgram(GrGLShaderBuilder* builder, 1.101 + const GrEffectStage* colorStages[], 1.102 + const GrEffectStage* coverageStages[]) { 1.103 + SkASSERT(0 == fProgramID); 1.104 + 1.105 + const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); 1.106 + 1.107 + // incoming color to current stage being processed. 1.108 + GrGLSLExpr4 inColor = builder->getInputColor(); 1.109 + 1.110 + fColorEffects.reset( 1.111 + builder->createAndEmitEffects(colorStages, 1.112 + fDesc.effectKeys(), 1.113 + fDesc.numColorEffects(), 1.114 + &inColor)); 1.115 + 1.116 + /////////////////////////////////////////////////////////////////////////// 1.117 + // compute the partial coverage 1.118 + GrGLSLExpr4 inCoverage = builder->getInputCoverage(); 1.119 + 1.120 + fCoverageEffects.reset( 1.121 + builder->createAndEmitEffects(coverageStages, 1.122 + fDesc.getEffectKeys() + fDesc.numColorEffects(), 1.123 + fDesc.numCoverageEffects(), 1.124 + &inCoverage)); 1.125 + 1.126 + if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(header.fCoverageOutput)) { 1.127 + const char* secondaryOutputName = builder->enableSecondaryOutput(); 1.128 + 1.129 + // default coeff to ones for kCoverage_DualSrcOutput 1.130 + GrGLSLExpr4 coeff(1); 1.131 + if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCoverageOutput) { 1.132 + // Get (1-A) into coeff 1.133 + coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inColor.a()); 1.134 + } else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput == header.fCoverageOutput) { 1.135 + // Get (1-RGBA) into coeff 1.136 + coeff = GrGLSLExpr4(1) - inColor; 1.137 + } 1.138 + // Get coeff * coverage into modulate and then write that to the dual source output. 1.139 + builder->fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inCoverage).c_str()); 1.140 + } 1.141 + 1.142 + /////////////////////////////////////////////////////////////////////////// 1.143 + // combine color and coverage as frag color 1.144 + 1.145 + // Get "color * coverage" into fragColor 1.146 + GrGLSLExpr4 fragColor = inColor * inCoverage; 1.147 + // Now tack on "+(1-coverage)dst onto the frag color if we were asked to do so. 1.148 + if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == header.fCoverageOutput) { 1.149 + GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inCoverage; 1.150 + 1.151 + GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(builder->dstColor()); 1.152 + 1.153 + fragColor = fragColor + dstContribution; 1.154 + } 1.155 + builder->fsCodeAppendf("\t%s = %s;\n", builder->getColorOutputName(), fragColor.c_str()); 1.156 + 1.157 + if (!builder->finish(&fProgramID)) { 1.158 + return false; 1.159 + } 1.160 + 1.161 + fUniformHandles.fRTHeightUni = builder->getRTHeightUniform(); 1.162 + fUniformHandles.fDstCopyTopLeftUni = builder->getDstCopyTopLeftUniform(); 1.163 + fUniformHandles.fDstCopyScaleUni = builder->getDstCopyScaleUniform(); 1.164 + fUniformHandles.fColorUni = builder->getColorUniform(); 1.165 + fUniformHandles.fCoverageUni = builder->getCoverageUniform(); 1.166 + fUniformHandles.fDstCopySamplerUni = builder->getDstCopySamplerUniform(); 1.167 + // This must be called after we set fDstCopySamplerUni above. 1.168 + this->initSamplerUniforms(); 1.169 + 1.170 + return true; 1.171 +} 1.172 + 1.173 +void GrGLProgram::initSamplerUniforms() { 1.174 + GL_CALL(UseProgram(fProgramID)); 1.175 + GrGLint texUnitIdx = 0; 1.176 + if (fUniformHandles.fDstCopySamplerUni.isValid()) { 1.177 + fUniformManager.setSampler(fUniformHandles.fDstCopySamplerUni, texUnitIdx); 1.178 + fDstCopyTexUnit = texUnitIdx++; 1.179 + } 1.180 + fColorEffects->initSamplers(fUniformManager, &texUnitIdx); 1.181 + fCoverageEffects->initSamplers(fUniformManager, &texUnitIdx); 1.182 +} 1.183 + 1.184 +/////////////////////////////////////////////////////////////////////////////// 1.185 + 1.186 +void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts, 1.187 + const GrEffectStage* colorStages[], 1.188 + const GrEffectStage* coverageStages[], 1.189 + const GrDeviceCoordTexture* dstCopy, 1.190 + SharedGLState* sharedState) { 1.191 + const GrDrawState& drawState = fGpu->getDrawState(); 1.192 + 1.193 + GrColor color; 1.194 + GrColor coverage; 1.195 + if (blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag) { 1.196 + color = 0; 1.197 + coverage = 0; 1.198 + } else if (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) { 1.199 + color = 0xffffffff; 1.200 + coverage = drawState.getCoverageColor(); 1.201 + } else { 1.202 + color = drawState.getColor(); 1.203 + coverage = drawState.getCoverageColor(); 1.204 + } 1.205 + 1.206 + this->setColor(drawState, color, sharedState); 1.207 + this->setCoverage(drawState, coverage, sharedState); 1.208 + this->setMatrixAndRenderTargetHeight(drawState); 1.209 + 1.210 + if (NULL != dstCopy) { 1.211 + if (fUniformHandles.fDstCopyTopLeftUni.isValid()) { 1.212 + fUniformManager.set2f(fUniformHandles.fDstCopyTopLeftUni, 1.213 + static_cast<GrGLfloat>(dstCopy->offset().fX), 1.214 + static_cast<GrGLfloat>(dstCopy->offset().fY)); 1.215 + fUniformManager.set2f(fUniformHandles.fDstCopyScaleUni, 1.216 + 1.f / dstCopy->texture()->width(), 1.217 + 1.f / dstCopy->texture()->height()); 1.218 + GrGLTexture* texture = static_cast<GrGLTexture*>(dstCopy->texture()); 1.219 + static GrTextureParams kParams; // the default is clamp, nearest filtering. 1.220 + fGpu->bindTexture(fDstCopyTexUnit, kParams, texture); 1.221 + } else { 1.222 + SkASSERT(!fUniformHandles.fDstCopyScaleUni.isValid()); 1.223 + SkASSERT(!fUniformHandles.fDstCopySamplerUni.isValid()); 1.224 + } 1.225 + } else { 1.226 + SkASSERT(!fUniformHandles.fDstCopyTopLeftUni.isValid()); 1.227 + SkASSERT(!fUniformHandles.fDstCopyScaleUni.isValid()); 1.228 + SkASSERT(!fUniformHandles.fDstCopySamplerUni.isValid()); 1.229 + } 1.230 + 1.231 + fColorEffects->setData(fGpu, fUniformManager, colorStages); 1.232 + fCoverageEffects->setData(fGpu, fUniformManager, coverageStages); 1.233 + 1.234 + 1.235 + // TexGen state applies to the the fixed function vertex shader. For custom shaders, it's 1.236 + // ignored, so we don't need to change the texgen settings in that case. 1.237 + if (!fHasVertexShader) { 1.238 + fGpu->flushTexGenSettings(fNumTexCoordSets); 1.239 + } 1.240 +} 1.241 + 1.242 +void GrGLProgram::setColor(const GrDrawState& drawState, 1.243 + GrColor color, 1.244 + SharedGLState* sharedState) { 1.245 + const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); 1.246 + if (!drawState.hasColorVertexAttribute()) { 1.247 + switch (header.fColorInput) { 1.248 + case GrGLProgramDesc::kAttribute_ColorInput: 1.249 + SkASSERT(-1 != header.fColorAttributeIndex); 1.250 + if (sharedState->fConstAttribColor != color || 1.251 + sharedState->fConstAttribColorIndex != header.fColorAttributeIndex) { 1.252 + // OpenGL ES only supports the float varieties of glVertexAttrib 1.253 + GrGLfloat c[4]; 1.254 + GrColorToRGBAFloat(color, c); 1.255 + GL_CALL(VertexAttrib4fv(header.fColorAttributeIndex, c)); 1.256 + sharedState->fConstAttribColor = color; 1.257 + sharedState->fConstAttribColorIndex = header.fColorAttributeIndex; 1.258 + } 1.259 + break; 1.260 + case GrGLProgramDesc::kUniform_ColorInput: 1.261 + if (fColor != color && fUniformHandles.fColorUni.isValid()) { 1.262 + // OpenGL ES doesn't support unsigned byte varieties of glUniform 1.263 + GrGLfloat c[4]; 1.264 + GrColorToRGBAFloat(color, c); 1.265 + fUniformManager.set4fv(fUniformHandles.fColorUni, 1, c); 1.266 + fColor = color; 1.267 + } 1.268 + sharedState->fConstAttribColorIndex = -1; 1.269 + break; 1.270 + case GrGLProgramDesc::kSolidWhite_ColorInput: 1.271 + case GrGLProgramDesc::kTransBlack_ColorInput: 1.272 + sharedState->fConstAttribColorIndex = -1; 1.273 + break; 1.274 + default: 1.275 + GrCrash("Unknown color type."); 1.276 + } 1.277 + } else { 1.278 + sharedState->fConstAttribColorIndex = -1; 1.279 + } 1.280 +} 1.281 + 1.282 +void GrGLProgram::setCoverage(const GrDrawState& drawState, 1.283 + GrColor coverage, 1.284 + SharedGLState* sharedState) { 1.285 + const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); 1.286 + if (!drawState.hasCoverageVertexAttribute()) { 1.287 + switch (header.fCoverageInput) { 1.288 + case GrGLProgramDesc::kAttribute_ColorInput: 1.289 + if (sharedState->fConstAttribCoverage != coverage || 1.290 + sharedState->fConstAttribCoverageIndex != header.fCoverageAttributeIndex) { 1.291 + // OpenGL ES only supports the float varieties of glVertexAttrib 1.292 + GrGLfloat c[4]; 1.293 + GrColorToRGBAFloat(coverage, c); 1.294 + GL_CALL(VertexAttrib4fv(header.fCoverageAttributeIndex, c)); 1.295 + sharedState->fConstAttribCoverage = coverage; 1.296 + sharedState->fConstAttribCoverageIndex = header.fCoverageAttributeIndex; 1.297 + } 1.298 + break; 1.299 + case GrGLProgramDesc::kUniform_ColorInput: 1.300 + if (fCoverage != coverage) { 1.301 + // OpenGL ES doesn't support unsigned byte varieties of glUniform 1.302 + GrGLfloat c[4]; 1.303 + GrColorToRGBAFloat(coverage, c); 1.304 + fUniformManager.set4fv(fUniformHandles.fCoverageUni, 1, c); 1.305 + fCoverage = coverage; 1.306 + } 1.307 + sharedState->fConstAttribCoverageIndex = -1; 1.308 + break; 1.309 + case GrGLProgramDesc::kSolidWhite_ColorInput: 1.310 + case GrGLProgramDesc::kTransBlack_ColorInput: 1.311 + sharedState->fConstAttribCoverageIndex = -1; 1.312 + break; 1.313 + default: 1.314 + GrCrash("Unknown coverage type."); 1.315 + } 1.316 + } else { 1.317 + sharedState->fConstAttribCoverageIndex = -1; 1.318 + } 1.319 +} 1.320 + 1.321 +void GrGLProgram::setMatrixAndRenderTargetHeight(const GrDrawState& drawState) { 1.322 + const GrRenderTarget* rt = drawState.getRenderTarget(); 1.323 + SkISize size; 1.324 + size.set(rt->width(), rt->height()); 1.325 + 1.326 + // Load the RT height uniform if it is needed to y-flip gl_FragCoord. 1.327 + if (fUniformHandles.fRTHeightUni.isValid() && 1.328 + fMatrixState.fRenderTargetSize.fHeight != size.fHeight) { 1.329 + fUniformManager.set1f(fUniformHandles.fRTHeightUni, SkIntToScalar(size.fHeight)); 1.330 + } 1.331 + 1.332 + if (!fHasVertexShader) { 1.333 + SkASSERT(!fUniformHandles.fViewMatrixUni.isValid()); 1.334 + fGpu->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin()); 1.335 + } else if (fMatrixState.fRenderTargetOrigin != rt->origin() || 1.336 + fMatrixState.fRenderTargetSize != size || 1.337 + !fMatrixState.fViewMatrix.cheapEqualTo(drawState.getViewMatrix())) { 1.338 + SkASSERT(fUniformHandles.fViewMatrixUni.isValid()); 1.339 + 1.340 + fMatrixState.fViewMatrix = drawState.getViewMatrix(); 1.341 + fMatrixState.fRenderTargetSize = size; 1.342 + fMatrixState.fRenderTargetOrigin = rt->origin(); 1.343 + 1.344 + GrGLfloat viewMatrix[3 * 3]; 1.345 + fMatrixState.getGLMatrix<3>(viewMatrix); 1.346 + fUniformManager.setMatrix3f(fUniformHandles.fViewMatrixUni, viewMatrix); 1.347 + } 1.348 +}