2 * Copyright 2011 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "GrGLProgram.h"
10 #include "builders/GrGLFullProgramBuilder.h"
11 #include "builders/GrGLFragmentOnlyProgramBuilder.h"
12 #include "GrAllocator.h"
13 #include "GrProcessor.h"
14 #include "GrCoordTransform.h"
15 #include "GrGLProcessor.h"
17 #include "GrGLPathRendering.h"
18 #include "GrGLShaderVar.h"
20 #include "GrOptDrawState.h"
21 #include "SkXfermode.h"
23 #define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
24 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X)
26 GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu,
27 const GrGLProgramDesc& desc,
28 const GrGeometryStage* geometryProcessor,
29 const GrFragmentStage* colorStages[],
30 const GrFragmentStage* coverageStages[]) {
31 SkAutoTDelete<GrGLProgramBuilder> builder;
32 if (desc.getHeader().fUseFragShaderOnly) {
33 SkASSERT(gpu->glCaps().pathRenderingSupport());
34 SkASSERT(gpu->glPathRendering()->texturingMode() ==
35 GrGLPathRendering::FixedFunction_TexturingMode);
36 SkASSERT(NULL == geometryProcessor);
37 builder.reset(SkNEW_ARGS(GrGLFragmentOnlyProgramBuilder, (gpu, desc)));
39 builder.reset(SkNEW_ARGS(GrGLFullProgramBuilder, (gpu, desc)));
41 if (builder->genProgram(geometryProcessor, colorStages, coverageStages)) {
42 SkASSERT(0 != builder->getProgramID());
43 return SkNEW_ARGS(GrGLProgram, (gpu, desc, *builder));
48 GrGLProgram::GrGLProgram(GrGpuGL* gpu,
49 const GrGLProgramDesc& desc,
50 const GrGLProgramBuilder& builder)
51 : fColor(GrColor_ILLEGAL)
52 , fCoverage(GrColor_ILLEGAL)
54 , fBuiltinUniformHandles(builder.getBuiltinUniformHandles())
55 , fGeometryProcessor(SkSafeRef(builder.getGeometryProcessor()))
56 , fColorEffects(SkRef(builder.getColorEffects()))
57 , fCoverageEffects(SkRef(builder.getCoverageEffects()))
58 , fProgramID(builder.getProgramID())
59 , fHasVertexShader(builder.hasVertexShader())
60 , fTexCoordSetCnt(builder.getTexCoordSetCount())
63 , fProgramDataManager(gpu, this, builder) {
64 this->initSamplerUniforms();
67 GrGLProgram::~GrGLProgram() {
69 GL_CALL(DeleteProgram(fProgramID));
73 void GrGLProgram::abandon() {
77 void GrGLProgram::initSamplerUniforms() {
78 GL_CALL(UseProgram(fProgramID));
79 GrGLint texUnitIdx = 0;
80 if (fBuiltinUniformHandles.fDstCopySamplerUni.isValid()) {
81 fProgramDataManager.setSampler(fBuiltinUniformHandles.fDstCopySamplerUni, texUnitIdx);
82 fDstCopyTexUnit = texUnitIdx++;
84 if (fGeometryProcessor.get()) {
85 fGeometryProcessor->initSamplers(fProgramDataManager, &texUnitIdx);
87 fColorEffects->initSamplers(fProgramDataManager, &texUnitIdx);
88 fCoverageEffects->initSamplers(fProgramDataManager, &texUnitIdx);
91 ///////////////////////////////////////////////////////////////////////////////
93 void GrGLProgram::setData(const GrOptDrawState& optState,
94 GrGpu::DrawType drawType,
95 const GrGeometryStage* geometryProcessor,
96 const GrFragmentStage* colorStages[],
97 const GrFragmentStage* coverageStages[],
98 const GrDeviceCoordTexture* dstCopy,
99 SharedGLState* sharedState) {
100 GrColor color = optState.getColor();
101 GrColor coverage = optState.getCoverageColor();
103 this->setColor(optState, color, sharedState);
104 this->setCoverage(optState, coverage, sharedState);
105 this->setMatrixAndRenderTargetHeight(drawType, optState);
108 if (fBuiltinUniformHandles.fDstCopyTopLeftUni.isValid()) {
109 fProgramDataManager.set2f(fBuiltinUniformHandles.fDstCopyTopLeftUni,
110 static_cast<GrGLfloat>(dstCopy->offset().fX),
111 static_cast<GrGLfloat>(dstCopy->offset().fY));
112 fProgramDataManager.set2f(fBuiltinUniformHandles.fDstCopyScaleUni,
113 1.f / dstCopy->texture()->width(),
114 1.f / dstCopy->texture()->height());
115 GrGLTexture* texture = static_cast<GrGLTexture*>(dstCopy->texture());
116 static GrTextureParams kParams; // the default is clamp, nearest filtering.
117 fGpu->bindTexture(fDstCopyTexUnit, kParams, texture);
119 SkASSERT(!fBuiltinUniformHandles.fDstCopyScaleUni.isValid());
120 SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid());
123 SkASSERT(!fBuiltinUniformHandles.fDstCopyTopLeftUni.isValid());
124 SkASSERT(!fBuiltinUniformHandles.fDstCopyScaleUni.isValid());
125 SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid());
128 if (fGeometryProcessor.get()) {
129 SkASSERT(geometryProcessor);
130 fGeometryProcessor->setData(fGpu, drawType, fProgramDataManager, geometryProcessor);
132 fColorEffects->setData(fGpu, drawType, fProgramDataManager, colorStages);
133 fCoverageEffects->setData(fGpu, drawType, fProgramDataManager, coverageStages);
135 // PathTexGen state applies to the the fixed function vertex shader. For
136 // custom shaders, it's ignored, so we don't need to change the texgen
137 // settings in that case.
138 if (!fHasVertexShader) {
139 fGpu->glPathRendering()->flushPathTexGenSettings(fTexCoordSetCnt);
143 void GrGLProgram::setColor(const GrOptDrawState& optState,
145 SharedGLState* sharedState) {
146 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
147 if (!optState.hasColorVertexAttribute()) {
148 switch (header.fColorInput) {
149 case GrGLProgramDesc::kAttribute_ColorInput:
150 SkASSERT(-1 != header.fColorAttributeIndex);
151 if (sharedState->fConstAttribColor != color ||
152 sharedState->fConstAttribColorIndex != header.fColorAttributeIndex) {
153 // OpenGL ES only supports the float varieties of glVertexAttrib
155 GrColorToRGBAFloat(color, c);
156 GL_CALL(VertexAttrib4fv(header.fColorAttributeIndex, c));
157 sharedState->fConstAttribColor = color;
158 sharedState->fConstAttribColorIndex = header.fColorAttributeIndex;
161 case GrGLProgramDesc::kUniform_ColorInput:
162 if (fColor != color && fBuiltinUniformHandles.fColorUni.isValid()) {
163 // OpenGL ES doesn't support unsigned byte varieties of glUniform
165 GrColorToRGBAFloat(color, c);
166 fProgramDataManager.set4fv(fBuiltinUniformHandles.fColorUni, 1, c);
169 sharedState->fConstAttribColorIndex = -1;
171 case GrGLProgramDesc::kAllOnes_ColorInput:
172 sharedState->fConstAttribColorIndex = -1;
175 SkFAIL("Unexpected color type.");
178 sharedState->fConstAttribColorIndex = -1;
182 void GrGLProgram::setCoverage(const GrOptDrawState& optState,
184 SharedGLState* sharedState) {
185 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
186 if (!optState.hasCoverageVertexAttribute()) {
187 switch (header.fCoverageInput) {
188 case GrGLProgramDesc::kAttribute_ColorInput:
189 if (sharedState->fConstAttribCoverage != coverage ||
190 sharedState->fConstAttribCoverageIndex != header.fCoverageAttributeIndex) {
191 // OpenGL ES only supports the float varieties of glVertexAttrib
193 GrColorToRGBAFloat(coverage, c);
194 GL_CALL(VertexAttrib4fv(header.fCoverageAttributeIndex, c));
195 sharedState->fConstAttribCoverage = coverage;
196 sharedState->fConstAttribCoverageIndex = header.fCoverageAttributeIndex;
199 case GrGLProgramDesc::kUniform_ColorInput:
200 if (fCoverage != coverage) {
201 // OpenGL ES doesn't support unsigned byte varieties of glUniform
203 GrColorToRGBAFloat(coverage, c);
204 fProgramDataManager.set4fv(fBuiltinUniformHandles.fCoverageUni, 1, c);
205 fCoverage = coverage;
207 sharedState->fConstAttribCoverageIndex = -1;
209 case GrGLProgramDesc::kAllOnes_ColorInput:
210 sharedState->fConstAttribCoverageIndex = -1;
213 SkFAIL("Unexpected coverage type.");
216 sharedState->fConstAttribCoverageIndex = -1;
220 void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
221 const GrOptDrawState& optState) {
222 const GrRenderTarget* rt = optState.getRenderTarget();
224 size.set(rt->width(), rt->height());
226 // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
227 if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
228 fMatrixState.fRenderTargetSize.fHeight != size.fHeight) {
229 fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni,
230 SkIntToScalar(size.fHeight));
233 if (GrGpu::IsPathRenderingDrawType(drawType)) {
234 fGpu->glPathRendering()->setProjectionMatrix(optState.getViewMatrix(), size, rt->origin());
235 } else if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
236 fMatrixState.fRenderTargetSize != size ||
237 !fMatrixState.fViewMatrix.cheapEqualTo(optState.getViewMatrix())) {
238 SkASSERT(fBuiltinUniformHandles.fViewMatrixUni.isValid());
240 fMatrixState.fViewMatrix = optState.getViewMatrix();
241 fMatrixState.fRenderTargetSize = size;
242 fMatrixState.fRenderTargetOrigin = rt->origin();
244 GrGLfloat viewMatrix[3 * 3];
245 fMatrixState.getGLMatrix<3>(viewMatrix);
246 fProgramDataManager.setMatrix3f(fBuiltinUniformHandles.fViewMatrixUni, viewMatrix);
248 GrGLfloat rtAdjustmentVec[4];
249 fMatrixState.getRTAdjustmentVec(rtAdjustmentVec);
250 fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);