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
Create(GrGpuGL * gpu,const GrGLProgramDesc & desc,const GrEffectStage * colorStages[],const GrEffectStage * coverageStages[])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
GrGLProgram(GrGpuGL * gpu,const GrGLProgramDesc & desc,GrGLUniformManager * uman,const GrGLShaderBuilder::GenProgramOutput & builderOutput)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
~GrGLProgram()51 GrGLProgram::~GrGLProgram() {
52 if (fBuilderOutput.fProgramID) {
53 GL_CALL(DeleteProgram(fBuilderOutput.fProgramID));
54 }
55 }
56
abandon()57 void GrGLProgram::abandon() {
58 fBuilderOutput.fProgramID = 0;
59 }
60
overrideBlend(GrBlendCoeff * srcCoeff,GrBlendCoeff * dstCoeff) const61 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
initSamplerUniforms()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
setData(GrDrawState::BlendOptFlags blendOpts,const GrEffectStage * colorStages[],const GrEffectStage * coverageStages[],const GrDeviceCoordTexture * dstCopy,SharedGLState * sharedState)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
setColor(const GrDrawState & drawState,GrColor color,SharedGLState * sharedState)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
setCoverage(const GrDrawState & drawState,GrColor coverage,SharedGLState * sharedState)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
setMatrixAndRenderTargetHeight(const GrDrawState & drawState)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