1/*
2 * Copyright 2014 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 "GrGLFullProgramBuilder.h"
9#include "../GrGLGeometryProcessor.h"
10#include "../GrGpuGL.h"
11
12GrGLFullProgramBuilder::GrGLFullProgramBuilder(GrGpuGL* gpu,
13                                               const GrGLProgramDesc& desc)
14    : INHERITED(gpu, desc)
15    , fGLGeometryProcessorEmitter(this)
16    , fGS(this)
17    , fVS(this) {
18}
19
20void
21GrGLFullProgramBuilder::createAndEmitEffects(const GrGeometryStage* geometryProcessor,
22                                             const GrFragmentStage* colorStages[],
23                                             const GrFragmentStage* coverageStages[],
24                                             GrGLSLExpr4* inputColor,
25                                             GrGLSLExpr4* inputCoverage) {
26    fVS.emitCodeBeforeEffects(inputColor, inputCoverage);
27
28    ///////////////////////////////////////////////////////////////////////////
29    // emit the per-effect code for both color and coverage effects
30
31    EffectKeyProvider colorKeyProvider(&this->desc(), EffectKeyProvider::kColor_EffectType);
32    fColorEffects.reset(this->onCreateAndEmitEffects(colorStages,
33                                                     this->desc().numColorEffects(),
34                                                     colorKeyProvider,
35                                                     inputColor));
36
37    if (geometryProcessor) {
38        const GrGeometryProcessor& gp = *geometryProcessor->getGeometryProcessor();
39        fGLGeometryProcessorEmitter.set(&gp);
40        fEffectEmitter = &fGLGeometryProcessorEmitter;
41        fVS.emitAttributes(gp);
42        GrGLSLExpr4 gpInputCoverage = *inputCoverage;
43        GrGLSLExpr4 gpOutputCoverage;
44        EffectKeyProvider gpKeyProvider(&this->desc(),
45                EffectKeyProvider::kGeometryProcessor_EffectType);
46        bool useLocalCoords = this->getVertexShaderBuilder()->hasExplicitLocalCoords();
47        fProgramEffects.reset(SkNEW_ARGS(GrGLVertexProgramEffects, (1, useLocalCoords)));
48        this->INHERITED::emitEffect(*geometryProcessor, 0, gpKeyProvider, &gpInputCoverage,
49                                    &gpOutputCoverage);
50        fGeometryProcessor.reset(fProgramEffects.detach());
51        *inputCoverage = gpOutputCoverage;
52    }
53
54    EffectKeyProvider coverageKeyProvider(&this->desc(), EffectKeyProvider::kCoverage_EffectType);
55    fCoverageEffects.reset(this->onCreateAndEmitEffects(coverageStages,
56                                                        this->desc().numCoverageEffects(),
57                                                        coverageKeyProvider,
58                                                        inputCoverage));
59
60     fVS.emitCodeAfterEffects();
61}
62
63void GrGLFullProgramBuilder::addVarying(GrSLType type,
64                                        const char* name,
65                                        const char** vsOutName,
66                                        const char** fsInName,
67                                        GrGLShaderVar::Precision fsPrecision) {
68    fVS.addVarying(type, name, vsOutName);
69
70    SkString* fsInputName = fVS.fOutputs.back().accessName();
71
72#if GR_GL_EXPERIMENTAL_GS
73    if (desc().getHeader().fExperimentalGS) {
74       // TODO let the caller use these names
75       fGS.addVarying(type, fsInputName->c_str(), NULL);
76       fsInputName = fGS.fOutputs.back().accessName();
77    }
78#endif
79    fFS.addVarying(type, fsInputName->c_str(), fsInName, fsPrecision);
80}
81
82GrGLFullProgramBuilder::VaryingHandle
83GrGLFullProgramBuilder::addSeparableVarying(GrSLType type,
84                                            const char* name,
85                                            const char** vsOutName,
86                                            const char** fsInName) {
87    addVarying(type, name, vsOutName, fsInName);
88    SeparableVaryingInfo& varying = fSeparableVaryingInfos.push_back();
89    varying.fVariable = fFS.fInputs.back();
90    return VaryingHandle::CreateFromSeparableVaryingIndex(fSeparableVaryingInfos.count() - 1);
91}
92
93GrGLProgramEffects* GrGLFullProgramBuilder::onCreateAndEmitEffects(
94        const GrFragmentStage* effectStages[],
95        int effectCnt,
96        const GrGLProgramDesc::EffectKeyProvider& keyProvider,
97        GrGLSLExpr4* inOutFSColor) {
98    fProgramEffects.reset(SkNEW_ARGS(GrGLVertexProgramEffects,
99                                 (effectCnt,
100                                  this->getVertexShaderBuilder()->hasExplicitLocalCoords())));
101    this->INHERITED::createAndEmitEffects(effectStages,
102                                          effectCnt,
103                                          keyProvider,
104                                          inOutFSColor);
105    return fProgramEffects.detach();
106}
107
108void GrGLFullProgramBuilder::emitEffect(const GrProcessorStage& stage,
109                                        const GrProcessorKey& key,
110                                        const char* outColor,
111                                        const char* inColor,
112                                        int stageIndex) {
113    SkASSERT(fProgramEffects.get());
114    const GrProcessor& effect = *stage.getProcessor();
115    SkSTArray<2, GrGLProcessor::TransformedCoords> coords(effect.numTransforms());
116    SkSTArray<4, GrGLProcessor::TextureSampler> samplers(effect.numTextures());
117
118    this->emitTransforms(stage, &coords);
119    this->emitSamplers(effect, &samplers);
120
121    SkASSERT(fEffectEmitter);
122    GrGLProcessor* glEffect = fEffectEmitter->createGLInstance();
123    fProgramEffects->addEffect(glEffect);
124
125    // Enclose custom code in a block to avoid namespace conflicts
126    SkString openBrace;
127    openBrace.printf("{ // Stage %d: %s\n", stageIndex, glEffect->name());
128    fFS.codeAppend(openBrace.c_str());
129    fVS.codeAppend(openBrace.c_str());
130
131    fEffectEmitter->emit(key, outColor, inColor, coords, samplers);
132
133    fVS.codeAppend("\t}\n");
134    fFS.codeAppend("\t}\n");
135}
136
137void GrGLFullProgramBuilder::emitTransforms(const GrProcessorStage& effectStage,
138                                            GrGLProcessor::TransformedCoordsArray* outCoords) {
139    SkTArray<GrGLVertexProgramEffects::Transform, true>& transforms =
140            fProgramEffects->addTransforms();
141    const GrProcessor* effect = effectStage.getProcessor();
142    int numTransforms = effect->numTransforms();
143    transforms.push_back_n(numTransforms);
144
145    SkTArray<GrGLVertexProgramEffects::PathTransform, true>* pathTransforms = NULL;
146    const GrGLCaps* glCaps = this->ctxInfo().caps();
147    if (glCaps->pathRenderingSupport() &&
148        this->gpu()->glPathRendering()->texturingMode() ==
149           GrGLPathRendering::SeparableShaders_TexturingMode) {
150        pathTransforms = &fProgramEffects->addPathTransforms();
151        pathTransforms->push_back_n(numTransforms);
152    }
153
154    for (int t = 0; t < numTransforms; t++) {
155        const char* uniName = "StageMatrix";
156        GrSLType varyingType =
157                effectStage.isPerspectiveCoordTransform(t, fVS.hasExplicitLocalCoords()) ?
158                        kVec3f_GrSLType :
159                        kVec2f_GrSLType;
160
161        SkString suffixedUniName;
162        if (0 != t) {
163            suffixedUniName.append(uniName);
164            suffixedUniName.appendf("_%i", t);
165            uniName = suffixedUniName.c_str();
166        }
167        transforms[t].fHandle = this->addUniform(GrGLProgramBuilder::kVertex_Visibility,
168                                                 kMat33f_GrSLType,
169                                                 uniName,
170                                                 &uniName);
171
172        const char* varyingName = "MatrixCoord";
173        SkString suffixedVaryingName;
174        if (0 != t) {
175            suffixedVaryingName.append(varyingName);
176            suffixedVaryingName.appendf("_%i", t);
177            varyingName = suffixedVaryingName.c_str();
178        }
179        const char* vsVaryingName;
180        const char* fsVaryingName;
181        if (pathTransforms) {
182            (*pathTransforms)[t].fHandle =
183                this->addSeparableVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
184            (*pathTransforms)[t].fType = varyingType;
185        } else {
186            this->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
187        }
188
189        const GrGLShaderVar& coords =
190                kPosition_GrCoordSet == effect->coordTransform(t).sourceCoords() ?
191                                          fVS.positionAttribute() :
192                                          fVS.localCoordsAttribute();
193        // varying = matrix * coords (logically)
194        SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
195        if (kVec2f_GrSLType == varyingType) {
196            fVS.codeAppendf("%s = (%s * vec3(%s, 1)).xy;",
197                            vsVaryingName, uniName, coords.c_str());
198        } else {
199            fVS.codeAppendf("%s = %s * vec3(%s, 1);",
200                            vsVaryingName, uniName, coords.c_str());
201        }
202        SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords,
203                               (SkString(fsVaryingName), varyingType));
204    }
205}
206
207bool GrGLFullProgramBuilder::compileAndAttachShaders(GrGLuint programId,
208                                                     SkTDArray<GrGLuint>* shaderIds) const {
209    return INHERITED::compileAndAttachShaders(programId, shaderIds)
210         && fVS.compileAndAttachShaders(programId, shaderIds)
211#if GR_GL_EXPERIMENTAL_GS
212         && (!desc().getHeader().fExperimentalGS
213                 || fGS.compileAndAttachShaders(programId, shaderIds))
214#endif
215         ;
216}
217
218void GrGLFullProgramBuilder::bindProgramLocations(GrGLuint programId) {
219    fVS.bindProgramLocations(programId);
220    INHERITED::bindProgramLocations(programId);
221}
222