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