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 "builders/GrGLFullProgramBuilder.h"
11#include "builders/GrGLFragmentOnlyProgramBuilder.h"
12#include "GrAllocator.h"
13#include "GrProcessor.h"
14#include "GrCoordTransform.h"
15#include "GrGLProcessor.h"
16#include "GrGpuGL.h"
17#include "GrGLPathRendering.h"
18#include "GrGLShaderVar.h"
19#include "GrGLSL.h"
20#include "GrOptDrawState.h"
21#include "SkXfermode.h"
22
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)
25
26GrGLProgram* 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)));
38    } else {
39        builder.reset(SkNEW_ARGS(GrGLFullProgramBuilder, (gpu, desc)));
40    }
41    if (builder->genProgram(geometryProcessor, colorStages, coverageStages)) {
42        SkASSERT(0 != builder->getProgramID());
43        return SkNEW_ARGS(GrGLProgram, (gpu, desc, *builder));
44    }
45    return NULL;
46}
47
48GrGLProgram::GrGLProgram(GrGpuGL* gpu,
49                         const GrGLProgramDesc& desc,
50                         const GrGLProgramBuilder& builder)
51    : fColor(GrColor_ILLEGAL)
52    , fCoverage(GrColor_ILLEGAL)
53    , fDstCopyTexUnit(-1)
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())
61    , fDesc(desc)
62    , fGpu(gpu)
63    , fProgramDataManager(gpu, this, builder) {
64    this->initSamplerUniforms();
65}
66
67GrGLProgram::~GrGLProgram() {
68    if (fProgramID) {
69        GL_CALL(DeleteProgram(fProgramID));
70    }
71}
72
73void GrGLProgram::abandon() {
74    fProgramID = 0;
75}
76
77void 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++;
83    }
84    if (fGeometryProcessor.get()) {
85        fGeometryProcessor->initSamplers(fProgramDataManager, &texUnitIdx);
86    }
87    fColorEffects->initSamplers(fProgramDataManager, &texUnitIdx);
88    fCoverageEffects->initSamplers(fProgramDataManager, &texUnitIdx);
89}
90
91///////////////////////////////////////////////////////////////////////////////
92
93void 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();
102
103    this->setColor(optState, color, sharedState);
104    this->setCoverage(optState, coverage, sharedState);
105    this->setMatrixAndRenderTargetHeight(drawType, optState);
106
107    if (dstCopy) {
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);
118        } else {
119            SkASSERT(!fBuiltinUniformHandles.fDstCopyScaleUni.isValid());
120            SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid());
121        }
122    } else {
123        SkASSERT(!fBuiltinUniformHandles.fDstCopyTopLeftUni.isValid());
124        SkASSERT(!fBuiltinUniformHandles.fDstCopyScaleUni.isValid());
125        SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid());
126    }
127
128    if (fGeometryProcessor.get()) {
129        SkASSERT(geometryProcessor);
130        fGeometryProcessor->setData(fGpu, drawType, fProgramDataManager, geometryProcessor);
131    }
132    fColorEffects->setData(fGpu, drawType, fProgramDataManager, colorStages);
133    fCoverageEffects->setData(fGpu, drawType, fProgramDataManager, coverageStages);
134
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);
140    }
141}
142
143void GrGLProgram::setColor(const GrOptDrawState& optState,
144                           GrColor color,
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
154                    GrGLfloat c[4];
155                    GrColorToRGBAFloat(color, c);
156                    GL_CALL(VertexAttrib4fv(header.fColorAttributeIndex, c));
157                    sharedState->fConstAttribColor = color;
158                    sharedState->fConstAttribColorIndex = header.fColorAttributeIndex;
159                }
160                break;
161            case GrGLProgramDesc::kUniform_ColorInput:
162                if (fColor != color && fBuiltinUniformHandles.fColorUni.isValid()) {
163                    // OpenGL ES doesn't support unsigned byte varieties of glUniform
164                    GrGLfloat c[4];
165                    GrColorToRGBAFloat(color, c);
166                    fProgramDataManager.set4fv(fBuiltinUniformHandles.fColorUni, 1, c);
167                    fColor = color;
168                }
169                sharedState->fConstAttribColorIndex = -1;
170                break;
171            case GrGLProgramDesc::kAllOnes_ColorInput:
172                sharedState->fConstAttribColorIndex = -1;
173                break;
174            default:
175                SkFAIL("Unexpected color type.");
176        }
177    } else {
178        sharedState->fConstAttribColorIndex = -1;
179    }
180}
181
182void GrGLProgram::setCoverage(const GrOptDrawState& optState,
183                              GrColor coverage,
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
192                    GrGLfloat c[4];
193                    GrColorToRGBAFloat(coverage, c);
194                    GL_CALL(VertexAttrib4fv(header.fCoverageAttributeIndex, c));
195                    sharedState->fConstAttribCoverage = coverage;
196                    sharedState->fConstAttribCoverageIndex = header.fCoverageAttributeIndex;
197                }
198                break;
199            case GrGLProgramDesc::kUniform_ColorInput:
200                if (fCoverage != coverage) {
201                    // OpenGL ES doesn't support unsigned byte varieties of glUniform
202                    GrGLfloat c[4];
203                    GrColorToRGBAFloat(coverage, c);
204                    fProgramDataManager.set4fv(fBuiltinUniformHandles.fCoverageUni, 1, c);
205                    fCoverage = coverage;
206                }
207                sharedState->fConstAttribCoverageIndex = -1;
208                break;
209            case GrGLProgramDesc::kAllOnes_ColorInput:
210                sharedState->fConstAttribCoverageIndex = -1;
211                break;
212            default:
213                SkFAIL("Unexpected coverage type.");
214        }
215    } else {
216        sharedState->fConstAttribCoverageIndex = -1;
217    }
218}
219
220void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
221                                                 const GrOptDrawState& optState) {
222    const GrRenderTarget* rt = optState.getRenderTarget();
223    SkISize size;
224    size.set(rt->width(), rt->height());
225
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));
231    }
232
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());
239
240        fMatrixState.fViewMatrix = optState.getViewMatrix();
241        fMatrixState.fRenderTargetSize = size;
242        fMatrixState.fRenderTargetOrigin = rt->origin();
243
244        GrGLfloat viewMatrix[3 * 3];
245        fMatrixState.getGLMatrix<3>(viewMatrix);
246        fProgramDataManager.setMatrix3f(fBuiltinUniformHandles.fViewMatrixUni, viewMatrix);
247
248        GrGLfloat rtAdjustmentVec[4];
249        fMatrixState.getRTAdjustmentVec(rtAdjustmentVec);
250        fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
251    }
252}
253