GrGLProgram.cpp revision 408d6125b32c86e1f81ce60465e3bf4491e755fc
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#include "GrGLProgram.h" 8 9#include "builders/GrGLFragmentOnlyProgramBuilder.h" 10#include "builders/GrGLFullProgramBuilder.h" 11#include "GrAllocator.h" 12#include "GrEffect.h" 13#include "GrCoordTransform.h" 14#include "GrGLEffect.h" 15#include "GrGpuGL.h" 16#include "GrGLPathRendering.h" 17#include "GrGLShaderVar.h" 18#include "GrGLSL.h" 19#include "GrOptDrawState.h" 20#include "SkXfermode.h" 21 22#define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X) 23#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X) 24 25GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu, 26 const GrGLProgramDesc& desc, 27 const GrEffectStage* geometryProcessor, 28 const GrEffectStage* colorStages[], 29 const GrEffectStage* coverageStages[]) { 30 SkAutoTDelete<GrGLProgramBuilder> builder; 31 if (!desc.getHeader().fRequiresVertexShader && 32 gpu->glCaps().pathRenderingSupport() && 33 gpu->glPathRendering()->texturingMode() == GrGLPathRendering::FixedFunction_TexturingMode) { 34 SkASSERT(NULL == geometryProcessor); 35 builder.reset(SkNEW_ARGS(GrGLFragmentOnlyProgramBuilder, (gpu, desc))); 36 } else { 37 builder.reset(SkNEW_ARGS(GrGLFullProgramBuilder, (gpu, desc))); 38 } 39 if (builder->genProgram(geometryProcessor, colorStages, coverageStages)) { 40 SkASSERT(0 != builder->getProgramID()); 41 return SkNEW_ARGS(GrGLProgram, (gpu, desc, *builder)); 42 } 43 return NULL; 44} 45 46GrGLProgram::GrGLProgram(GrGpuGL* gpu, 47 const GrGLProgramDesc& desc, 48 const GrGLProgramBuilder& builder) 49 : fColor(GrColor_ILLEGAL) 50 , fCoverage(GrColor_ILLEGAL) 51 , fDstCopyTexUnit(-1) 52 , fBuiltinUniformHandles(builder.getBuiltinUniformHandles()) 53 , fGeometryProcessor(SkSafeRef(builder.getGeometryProcessor())) 54 , fColorEffects(SkRef(builder.getColorEffects())) 55 , fCoverageEffects(SkRef(builder.getCoverageEffects())) 56 , fProgramID(builder.getProgramID()) 57 , fHasVertexShader(builder.hasVertexShader()) 58 , fTexCoordSetCnt(builder.getTexCoordSetCount()) 59 , fDesc(desc) 60 , fGpu(gpu) 61 , fProgramDataManager(gpu, this, builder) { 62 this->initSamplerUniforms(); 63} 64 65GrGLProgram::~GrGLProgram() { 66 if (fProgramID) { 67 GL_CALL(DeleteProgram(fProgramID)); 68 } 69} 70 71void GrGLProgram::abandon() { 72 fProgramID = 0; 73} 74 75void 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 SkFAIL("Unexpected coverage output"); 93 break; 94 } 95} 96 97void GrGLProgram::initSamplerUniforms() { 98 GL_CALL(UseProgram(fProgramID)); 99 GrGLint texUnitIdx = 0; 100 if (fBuiltinUniformHandles.fDstCopySamplerUni.isValid()) { 101 fProgramDataManager.setSampler(fBuiltinUniformHandles.fDstCopySamplerUni, texUnitIdx); 102 fDstCopyTexUnit = texUnitIdx++; 103 } 104 if (fGeometryProcessor.get()) { 105 fGeometryProcessor->initSamplers(fProgramDataManager, &texUnitIdx); 106 } 107 fColorEffects->initSamplers(fProgramDataManager, &texUnitIdx); 108 fCoverageEffects->initSamplers(fProgramDataManager, &texUnitIdx); 109} 110 111/////////////////////////////////////////////////////////////////////////////// 112 113void GrGLProgram::setData(const GrOptDrawState& optState, 114 GrGpu::DrawType drawType, 115 const GrEffectStage* geometryProcessor, 116 const GrEffectStage* colorStages[], 117 const GrEffectStage* coverageStages[], 118 const GrDeviceCoordTexture* dstCopy, 119 SharedGLState* sharedState) { 120 GrColor color = optState.getColor(); 121 GrColor coverage = optState.getCoverageColor(); 122 123 this->setColor(optState, color, sharedState); 124 this->setCoverage(optState, coverage, sharedState); 125 this->setMatrixAndRenderTargetHeight(drawType, optState); 126 127 if (dstCopy) { 128 if (fBuiltinUniformHandles.fDstCopyTopLeftUni.isValid()) { 129 fProgramDataManager.set2f(fBuiltinUniformHandles.fDstCopyTopLeftUni, 130 static_cast<GrGLfloat>(dstCopy->offset().fX), 131 static_cast<GrGLfloat>(dstCopy->offset().fY)); 132 fProgramDataManager.set2f(fBuiltinUniformHandles.fDstCopyScaleUni, 133 1.f / dstCopy->texture()->width(), 134 1.f / dstCopy->texture()->height()); 135 GrGLTexture* texture = static_cast<GrGLTexture*>(dstCopy->texture()); 136 static GrTextureParams kParams; // the default is clamp, nearest filtering. 137 fGpu->bindTexture(fDstCopyTexUnit, kParams, texture); 138 } else { 139 SkASSERT(!fBuiltinUniformHandles.fDstCopyScaleUni.isValid()); 140 SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid()); 141 } 142 } else { 143 SkASSERT(!fBuiltinUniformHandles.fDstCopyTopLeftUni.isValid()); 144 SkASSERT(!fBuiltinUniformHandles.fDstCopyScaleUni.isValid()); 145 SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid()); 146 } 147 148 if (fGeometryProcessor.get()) { 149 SkASSERT(geometryProcessor); 150 fGeometryProcessor->setData(fGpu, drawType,fProgramDataManager, geometryProcessor); 151 } 152 fColorEffects->setData(fGpu, drawType,fProgramDataManager, colorStages); 153 fCoverageEffects->setData(fGpu, drawType,fProgramDataManager, coverageStages); 154 155 // PathTexGen state applies to the the fixed function vertex shader. For 156 // custom shaders, it's ignored, so we don't need to change the texgen 157 // settings in that case. 158 if (!fHasVertexShader) { 159 fGpu->glPathRendering()->flushPathTexGenSettings(fTexCoordSetCnt); 160 } 161} 162 163void GrGLProgram::setColor(const GrOptDrawState& optState, 164 GrColor color, 165 SharedGLState* sharedState) { 166 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); 167 if (!optState.hasColorVertexAttribute()) { 168 switch (header.fColorInput) { 169 case GrGLProgramDesc::kAttribute_ColorInput: 170 SkASSERT(-1 != header.fColorAttributeIndex); 171 if (sharedState->fConstAttribColor != color || 172 sharedState->fConstAttribColorIndex != header.fColorAttributeIndex) { 173 // OpenGL ES only supports the float varieties of glVertexAttrib 174 GrGLfloat c[4]; 175 GrColorToRGBAFloat(color, c); 176 GL_CALL(VertexAttrib4fv(header.fColorAttributeIndex, c)); 177 sharedState->fConstAttribColor = color; 178 sharedState->fConstAttribColorIndex = header.fColorAttributeIndex; 179 } 180 break; 181 case GrGLProgramDesc::kUniform_ColorInput: 182 if (fColor != color && fBuiltinUniformHandles.fColorUni.isValid()) { 183 // OpenGL ES doesn't support unsigned byte varieties of glUniform 184 GrGLfloat c[4]; 185 GrColorToRGBAFloat(color, c); 186 fProgramDataManager.set4fv(fBuiltinUniformHandles.fColorUni, 1, c); 187 fColor = color; 188 } 189 sharedState->fConstAttribColorIndex = -1; 190 break; 191 case GrGLProgramDesc::kAllOnes_ColorInput: 192 sharedState->fConstAttribColorIndex = -1; 193 break; 194 default: 195 SkFAIL("Unexpected color type."); 196 } 197 } else { 198 sharedState->fConstAttribColorIndex = -1; 199 } 200} 201 202void GrGLProgram::setCoverage(const GrOptDrawState& optState, 203 GrColor coverage, 204 SharedGLState* sharedState) { 205 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); 206 if (!optState.hasCoverageVertexAttribute()) { 207 switch (header.fCoverageInput) { 208 case GrGLProgramDesc::kAttribute_ColorInput: 209 if (sharedState->fConstAttribCoverage != coverage || 210 sharedState->fConstAttribCoverageIndex != header.fCoverageAttributeIndex) { 211 // OpenGL ES only supports the float varieties of glVertexAttrib 212 GrGLfloat c[4]; 213 GrColorToRGBAFloat(coverage, c); 214 GL_CALL(VertexAttrib4fv(header.fCoverageAttributeIndex, c)); 215 sharedState->fConstAttribCoverage = coverage; 216 sharedState->fConstAttribCoverageIndex = header.fCoverageAttributeIndex; 217 } 218 break; 219 case GrGLProgramDesc::kUniform_ColorInput: 220 if (fCoverage != coverage) { 221 // OpenGL ES doesn't support unsigned byte varieties of glUniform 222 GrGLfloat c[4]; 223 GrColorToRGBAFloat(coverage, c); 224 fProgramDataManager.set4fv(fBuiltinUniformHandles.fCoverageUni, 1, c); 225 fCoverage = coverage; 226 } 227 sharedState->fConstAttribCoverageIndex = -1; 228 break; 229 case GrGLProgramDesc::kAllOnes_ColorInput: 230 sharedState->fConstAttribCoverageIndex = -1; 231 break; 232 default: 233 SkFAIL("Unexpected coverage type."); 234 } 235 } else { 236 sharedState->fConstAttribCoverageIndex = -1; 237 } 238} 239 240void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType, 241 const GrOptDrawState& optState) { 242 const GrRenderTarget* rt = optState.getRenderTarget(); 243 SkISize size; 244 size.set(rt->width(), rt->height()); 245 246 // Load the RT height uniform if it is needed to y-flip gl_FragCoord. 247 if (fBuiltinUniformHandles.fRTHeightUni.isValid() && 248 fMatrixState.fRenderTargetSize.fHeight != size.fHeight) { 249 fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, 250 SkIntToScalar(size.fHeight)); 251 } 252 253 if (GrGpu::IsPathRenderingDrawType(drawType)) { 254 fGpu->glPathRendering()->setProjectionMatrix(optState.getViewMatrix(), size, rt->origin()); 255 } else if (fMatrixState.fRenderTargetOrigin != rt->origin() || 256 fMatrixState.fRenderTargetSize != size || 257 !fMatrixState.fViewMatrix.cheapEqualTo(optState.getViewMatrix())) { 258 SkASSERT(fBuiltinUniformHandles.fViewMatrixUni.isValid()); 259 260 fMatrixState.fViewMatrix = optState.getViewMatrix(); 261 fMatrixState.fRenderTargetSize = size; 262 fMatrixState.fRenderTargetOrigin = rt->origin(); 263 264 GrGLfloat viewMatrix[3 * 3]; 265 fMatrixState.getGLMatrix<3>(viewMatrix); 266 fProgramDataManager.setMatrix3f(fBuiltinUniformHandles.fViewMatrixUni, viewMatrix); 267 268 GrGLfloat rtAdjustmentVec[4]; 269 fMatrixState.getRTAdjustmentVec(rtAdjustmentVec); 270 fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec); 271 } 272} 273