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