• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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