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