OLD | NEW |
(Empty) | |
| 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 |
| 12 GrGLFullProgramBuilder::GrGLFullProgramBuilder(GrGpuGL* gpu, const GrOptDrawStat
e& optState, |
| 13 const GrGLProgramDesc& desc) |
| 14 : INHERITED(gpu, optState, desc) |
| 15 , fGLGeometryProcessorEmitter(this) |
| 16 , fGS(this) |
| 17 , fVS(this) { |
| 18 } |
| 19 |
| 20 void |
| 21 GrGLFullProgramBuilder::createAndEmitEffects(const GrGeometryStage* geometryProc
essor, |
| 22 const GrFragmentStage* colorStages[
], |
| 23 const GrFragmentStage* coverageStag
es[], |
| 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().numColorEffect
s(), |
| 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()->hasExplicitLocalCo
ords(); |
| 47 fProgramEffects.reset(SkNEW_ARGS(GrGLVertexProgramEffects, (1, useLocalC
oords))); |
| 48 this->INHERITED::emitEffect(*geometryProcessor, 0, gpKeyProvider, &gpInp
utCoverage, |
| 49 &gpOutputCoverage); |
| 50 fGeometryProcessor.reset(fProgramEffects.detach()); |
| 51 *inputCoverage = gpOutputCoverage; |
| 52 } |
| 53 |
| 54 EffectKeyProvider coverageKeyProvider(&this->desc(), EffectKeyProvider::kCov
erage_EffectType); |
| 55 fCoverageEffects.reset(this->onCreateAndEmitEffects(coverageStages, |
| 56 this->desc().numCoverage
Effects(), |
| 57 coverageKeyProvider, |
| 58 inputCoverage)); |
| 59 |
| 60 fVS.emitCodeAfterEffects(); |
| 61 } |
| 62 |
| 63 void 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 |
| 82 GrGLFullProgramBuilder::VaryingHandle |
| 83 GrGLFullProgramBuilder::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 |
| 93 GrGLProgramEffects* 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()->hasExplicitLoc
alCoords()))); |
| 101 this->INHERITED::createAndEmitEffects(effectStages, |
| 102 effectCnt, |
| 103 keyProvider, |
| 104 inOutFSColor); |
| 105 return fProgramEffects.detach(); |
| 106 } |
| 107 |
| 108 void 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 |
| 137 void GrGLFullProgramBuilder::emitTransforms(const GrProcessorStage& effectStage, |
| 138 GrGLProcessor::TransformedCoordsArra
y* 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 = NU
LL; |
| 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.hasExplicitLocalC
oords()) ? |
| 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_Vis
ibility, |
| 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, &vsVaryingNa
me, &fsVaryingName); |
| 184 (*pathTransforms)[t].fType = varyingType; |
| 185 } else { |
| 186 this->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryin
gName); |
| 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 == varyingTyp
e); |
| 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 |
| 207 bool GrGLFullProgramBuilder::compileAndAttachShaders(GrGLuint programId, |
| 208 SkTDArray<GrGLuint>* shader
Ids) 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 |
| 218 void GrGLFullProgramBuilder::bindProgramLocations(GrGLuint programId) { |
| 219 fVS.bindProgramLocations(programId); |
| 220 INHERITED::bindProgramLocations(programId); |
| 221 } |
OLD | NEW |