2 * Copyright 2014 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "GrGLProgramBuilder.h"
9 #include "gl/GrGLProgram.h"
10 #include "gl/GrGLSLPrettyPrint.h"
11 #include "gl/GrGLUniformHandle.h"
12 #include "../GrGpuGL.h"
13 #include "GrCoordTransform.h"
14 #include "GrGLLegacyNvprProgramBuilder.h"
15 #include "GrGLNvprProgramBuilder.h"
16 #include "GrGLProgramBuilder.h"
17 #include "GrTexture.h"
19 #include "SkTraceEvent.h"
21 #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
22 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
24 // ES2 FS only guarantees mediump and lowp support
25 static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision;
27 //////////////////////////////////////////////////////////////////////////////
29 const int GrGLProgramBuilder::kVarsPerBlock = 8;
31 GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState,
32 GrGpu::DrawType drawType,
34 // create a builder. This will be handed off to effects so they can use it to add
35 // uniforms, varyings, textures, etc
36 SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(optState,
38 optState.hasGeometryProcessor(),
41 GrGLProgramBuilder* pb = builder.get();
42 const GrGLProgramDescBuilder::GLKeyHeader& header = GrGLProgramDescBuilder::GetHeader(pb->desc());
44 // emit code to read the dst copy texture, if necessary
45 if (GrGLFragmentShaderBuilder::kNoDstRead_DstReadKey != header.fDstReadKey
46 && !gpu->glCaps().fbFetchSupport()) {
47 pb->fFS.emitCodeToReadDstTexture();
50 // get the initial color and coverage to feed into the first effect in each effect chain
51 GrGLSLExpr4 inputColor;
52 GrGLSLExpr1 inputCoverage;
53 pb->setupUniformColorAndCoverageIfNeeded(&inputColor, &inputCoverage);
55 // if we have a vertex shader(we don't only if we are using NVPR or NVPR ES), then we may have
56 // to setup a few more things like builtin vertex attributes
57 bool hasVertexShader = !(header.fUseNvpr &&
58 gpu->glPathRendering()->texturingMode() ==
59 GrGLPathRendering::FixedFunction_TexturingMode);
60 if (hasVertexShader) {
61 pb->fVS.setupLocalCoords();
62 pb->fVS.transformGLToSkiaCoords();
63 if (header.fEmitsPointSize) {
64 pb->fVS.codeAppend("gl_PointSize = 1.0;");
66 if (GrProgramDesc::kAttribute_ColorInput == header.fColorInput) {
67 pb->fVS.setupBuiltinVertexAttribute("Color", &inputColor);
69 if (GrProgramDesc::kAttribute_ColorInput == header.fCoverageInput) {
70 pb->fVS.setupBuiltinVertexAttribute("Coverage", &inputCoverage);
74 // TODO: Once all stages can handle taking a float or vec4 and correctly handling them we can
75 // remove this cast to a vec4.
76 GrGLSLExpr4 inputCoverageVec4 = GrGLSLExpr4::VectorCast(inputCoverage);
78 pb->emitAndInstallProcs(optState, &inputColor, &inputCoverageVec4);
80 if (hasVertexShader) {
81 pb->fVS.transformSkiaToGLCoords();
84 // write the secondary color output if necessary
85 if (GrProgramDesc::kNone_SecondaryOutputType != header.fSecondaryOutputType) {
86 pb->fFS.enableSecondaryOutput(inputColor, inputCoverageVec4);
89 pb->fFS.combineColorAndCoverage(inputColor, inputCoverageVec4);
91 return pb->finalize();
95 GrGLProgramBuilder::CreateProgramBuilder(const GrOptDrawState& optState,
96 GrGpu::DrawType drawType,
97 bool hasGeometryProcessor,
99 const GrProgramDesc& desc = optState.programDesc();
100 if (GrGLProgramDescBuilder::GetHeader(desc).fUseNvpr) {
101 SkASSERT(gpu->glCaps().pathRenderingSupport());
102 SkASSERT(GrProgramDesc::kAttribute_ColorInput != desc.header().fColorInput);
103 SkASSERT(GrProgramDesc::kAttribute_ColorInput != desc.header().fCoverageInput);
104 SkASSERT(!hasGeometryProcessor);
105 if (gpu->glPathRendering()->texturingMode() ==
106 GrGLPathRendering::FixedFunction_TexturingMode) {
107 return SkNEW_ARGS(GrGLLegacyNvprProgramBuilder, (gpu, optState));
109 return SkNEW_ARGS(GrGLNvprProgramBuilder, (gpu, optState));
112 return SkNEW_ARGS(GrGLProgramBuilder, (gpu, optState));
116 /////////////////////////////////////////////////////////////////////////////
118 GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu, const GrOptDrawState& optState)
121 , fFS(this, optState.programDesc().header().fFragPosKey)
124 , fGeometryProcessor(NULL)
125 , fOptState(optState)
126 , fDesc(optState.programDesc())
128 , fUniforms(kVarsPerBlock) {
131 void GrGLProgramBuilder::addVarying(const char* name,
132 GrGLVarying* varying,
133 GrGLShaderVar::Precision fsPrecision) {
135 if (varying->vsVarying()) {
136 fVS.addVarying(name, varying);
138 if (fOptState.hasGeometryProcessor() && fOptState.getGeometryProcessor()->willUseGeoShader()) {
139 fGS.addVarying(name, varying);
141 if (varying->fsVarying()) {
142 fFS.addVarying(varying, fsPrecision);
146 void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name) {
147 if ('\0' == prefix) {
150 out->printf("%c%s", prefix, name);
153 if (out->endsWith('_')) {
154 // Names containing "__" are reserved.
157 out->appendf("_Stage%d", fStageIndex);
161 GrGLProgramDataManager::UniformHandle GrGLProgramBuilder::addUniformArray(uint32_t visibility,
165 const char** outName) {
166 SkASSERT(name && strlen(name));
167 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFragment_Visibility);
168 SkASSERT(0 == (~kVisibilityMask & visibility));
169 SkASSERT(0 != visibility);
171 UniformInfo& uni = fUniforms.push_back();
172 uni.fVariable.setType(type);
173 uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
174 this->nameVariable(uni.fVariable.accessName(), 'u', name);
175 uni.fVariable.setArrayCount(count);
176 uni.fVisibility = visibility;
178 // If it is visible in both the VS and FS, the precision must match.
179 // We declare a default FS precision, but not a default VS. So set the var
180 // to use the default FS precision.
181 if ((kVertex_Visibility | kFragment_Visibility) == visibility) {
182 // the fragment and vertex precisions must match
183 uni.fVariable.setPrecision(kDefaultFragmentPrecision);
187 *outName = uni.fVariable.c_str();
189 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fUniforms.count() - 1);
192 void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility,
193 SkString* out) const {
194 for (int i = 0; i < fUniforms.count(); ++i) {
195 if (fUniforms[i].fVisibility & visibility) {
196 fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out);
202 const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const {
203 return fGpu->ctxInfo();
206 void GrGLProgramBuilder::setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor,
207 GrGLSLExpr1* inputCoverage) {
208 const GrProgramDesc::KeyHeader& header = this->header();
209 if (GrProgramDesc::kUniform_ColorInput == header.fColorInput) {
211 fUniformHandles.fColorUni =
212 this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
216 *inputColor = GrGLSLExpr4(name);
217 } else if (GrProgramDesc::kAllOnes_ColorInput == header.fColorInput) {
218 *inputColor = GrGLSLExpr4(1);
220 if (GrProgramDesc::kUniform_ColorInput == header.fCoverageInput) {
222 fUniformHandles.fCoverageUni =
223 this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
227 *inputCoverage = GrGLSLExpr1(name);
228 } else if (GrProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) {
229 *inputCoverage = GrGLSLExpr1(1);
233 void GrGLProgramBuilder::emitAndInstallProcs(const GrOptDrawState& optState,
234 GrGLSLExpr4* inputColor,
235 GrGLSLExpr4* inputCoverage) {
236 fFragmentProcessors.reset(SkNEW(GrGLInstalledFragProcs));
237 int numProcs = optState.numFragmentStages();
238 this->emitAndInstallFragProcs(0, optState.numColorStages(), inputColor);
239 if (optState.hasGeometryProcessor()) {
240 const GrGeometryProcessor& gp = *optState.getGeometryProcessor();
241 fVS.emitAttributes(gp);
242 ProcKeyProvider keyProvider(&fDesc,
243 ProcKeyProvider::kGeometry_ProcessorType,
244 GrGLProgramDescBuilder::kProcessorKeyOffsetsAndLengthOffset);
246 this->emitAndInstallProc<GrGeometryProcessor>(gp, 0, keyProvider, *inputCoverage, &output);
247 *inputCoverage = output;
249 this->emitAndInstallFragProcs(optState.numColorStages(), numProcs, inputCoverage);
252 void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut) {
253 ProcKeyProvider keyProvider(&fDesc,
254 ProcKeyProvider::kFragment_ProcessorType,
255 GrGLProgramDescBuilder::kProcessorKeyOffsetsAndLengthOffset);
256 for (int e = procOffset; e < numProcs; ++e) {
258 const GrFragmentStage& stage = fOptState.getFragmentStage(e);
259 this->emitAndInstallProc<GrFragmentStage>(stage, e, keyProvider, *inOut, &output);
264 // TODO Processors cannot output zeros because an empty string is all 1s
265 // the fix is to allow effects to take the GrGLSLExpr4 directly
266 template <class Proc>
267 void GrGLProgramBuilder::emitAndInstallProc(const Proc& proc,
269 const ProcKeyProvider& keyProvider,
270 const GrGLSLExpr4& input,
271 GrGLSLExpr4* output) {
272 // Program builders have a bit of state we need to clear with each effect
273 AutoStageAdvance adv(this);
275 // create var to hold stage result
276 SkString outColorName;
277 this->nameVariable(&outColorName, '\0', "output");
278 fFS.codeAppendf("vec4 %s;", outColorName.c_str());
279 *output = outColorName;
281 // Enclose custom code in a block to avoid namespace conflicts
283 openBrace.printf("{ // Stage %d\n", fStageIndex);
284 fFS.codeAppend(openBrace.c_str());
286 this->emitAndInstallProc(proc, keyProvider.get(index), output->c_str(),
287 input.isOnes() ? NULL : input.c_str());
292 void GrGLProgramBuilder::emitAndInstallProc(const GrFragmentStage& fs,
293 const GrProcessorKey& key,
294 const char* outColor,
295 const char* inColor) {
296 GrGLInstalledFragProc* ifp = SkNEW_ARGS(GrGLInstalledFragProc, (fVS.hasLocalCoords()));
298 const GrFragmentProcessor& fp = *fs.getProcessor();
299 ifp->fGLProc.reset(fp.getFactory().createGLInstance(fp));
301 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(fp.numTextures());
302 this->emitSamplers(fp, &samplers, ifp);
304 // Fragment processors can have coord transforms
305 SkSTArray<2, GrGLProcessor::TransformedCoords> coords(fp.numTransforms());
306 this->emitTransforms(fs, &coords, ifp);
308 ifp->fGLProc->emitCode(this, fp, key, outColor, inColor, coords, samplers);
310 // We have to check that effects and the code they emit are consistent, ie if an effect
311 // asks for dst color, then the emit code needs to follow suit
313 fFragmentProcessors->fProcs.push_back(ifp);
316 void GrGLProgramBuilder::emitAndInstallProc(const GrGeometryProcessor& gp,
317 const GrProcessorKey& key,
318 const char* outColor,
319 const char* inColor) {
320 SkASSERT(!fGeometryProcessor);
321 fGeometryProcessor = SkNEW(GrGLInstalledGeoProc);
323 fGeometryProcessor->fGLProc.reset(gp.getFactory().createGLInstance(gp));
325 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(gp.numTextures());
326 this->emitSamplers(gp, &samplers, fGeometryProcessor);
328 GrGLGeometryProcessor::EmitArgs args(this, gp, key, outColor, inColor, samplers);
329 fGeometryProcessor->fGLProc->emitCode(args);
331 // We have to check that effects and the code they emit are consistent, ie if an effect
332 // asks for dst color, then the emit code needs to follow suit
336 void GrGLProgramBuilder::verify(const GrGeometryProcessor& gp) {
337 SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition());
340 void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) {
341 SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition());
342 SkASSERT(fFS.hasReadDstColor() == fp.willReadDstColor());
345 void GrGLProgramBuilder::emitTransforms(const GrFragmentStage& effectStage,
346 GrGLProcessor::TransformedCoordsArray* outCoords,
347 GrGLInstalledFragProc* ifp) {
348 const GrFragmentProcessor* effect = effectStage.getProcessor();
349 int numTransforms = effect->numTransforms();
350 ifp->fTransforms.push_back_n(numTransforms);
352 for (int t = 0; t < numTransforms; t++) {
353 const char* uniName = "StageMatrix";
354 GrSLType varyingType =
355 effectStage.isPerspectiveCoordTransform(t, fVS.hasLocalCoords()) ?
359 SkString suffixedUniName;
361 suffixedUniName.append(uniName);
362 suffixedUniName.appendf("_%i", t);
363 uniName = suffixedUniName.c_str();
365 ifp->fTransforms[t].fHandle = this->addUniform(GrGLProgramBuilder::kVertex_Visibility,
368 &uniName).toShaderBuilderIndex();
370 const char* varyingName = "MatrixCoord";
371 SkString suffixedVaryingName;
373 suffixedVaryingName.append(varyingName);
374 suffixedVaryingName.appendf("_%i", t);
375 varyingName = suffixedVaryingName.c_str();
377 GrGLVertToFrag v(varyingType);
378 this->addVarying(varyingName, &v);
380 const GrGLShaderVar& coords =
381 kPosition_GrCoordSet == effect->coordTransform(t).sourceCoords() ?
382 fVS.positionAttribute() :
383 fVS.localCoordsAttribute();
385 // varying = matrix * coords (logically)
386 SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
387 if (kVec2f_GrSLType == varyingType) {
388 fVS.codeAppendf("%s = (%s * vec3(%s, 1)).xy;",
389 v.vsOut(), uniName, coords.c_str());
391 fVS.codeAppendf("%s = %s * vec3(%s, 1);",
392 v.vsOut(), uniName, coords.c_str());
394 SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords,
395 (SkString(v.fsIn()), varyingType));
399 void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor,
400 GrGLProcessor::TextureSamplerArray* outSamplers,
401 GrGLInstalledProc* ip) {
402 int numTextures = processor.numTextures();
403 ip->fSamplers.push_back_n(numTextures);
405 for (int t = 0; t < numTextures; ++t) {
406 name.printf("Sampler%d", t);
407 ip->fSamplers[t].fUniform = this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
410 SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLProcessor::TextureSampler,
411 (ip->fSamplers[t].fUniform, processor.textureAccess(t)));
415 GrGLProgram* GrGLProgramBuilder::finalize() {
416 // verify we can get a program id
418 GL_CALL_RET(programID, CreateProgram());
419 if (0 == programID) {
423 // compile shaders and bind attributes / uniforms
424 SkTDArray<GrGLuint> shadersToDelete;
425 if (!fFS.compileAndAttachShaders(programID, &shadersToDelete)) {
426 this->cleanupProgram(programID, shadersToDelete);
429 if (!(GrGLProgramDescBuilder::GetHeader(fDesc).fUseNvpr &&
430 fGpu->glPathRendering()->texturingMode() ==
431 GrGLPathRendering::FixedFunction_TexturingMode)) {
432 if (!fVS.compileAndAttachShaders(programID, &shadersToDelete)) {
433 this->cleanupProgram(programID, shadersToDelete);
436 fVS.bindVertexAttributes(programID);
438 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
439 if (usingBindUniform) {
440 this->bindUniformLocations(programID);
442 fFS.bindFragmentShaderLocations(programID);
443 GL_CALL(LinkProgram(programID));
445 // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
446 bool checkLinked = !fGpu->ctxInfo().isChromium();
451 checkLinkStatus(programID);
453 if (!usingBindUniform) {
454 this->resolveUniformLocations(programID);
457 this->cleanupShaders(shadersToDelete);
459 return this->createProgram(programID);
462 void GrGLProgramBuilder::bindUniformLocations(GrGLuint programID) {
463 int count = fUniforms.count();
464 for (int i = 0; i < count; ++i) {
465 GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_str()));
466 fUniforms[i].fLocation = i;
470 bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) {
471 GrGLint linked = GR_GL_INIT_ZERO;
472 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
474 GrGLint infoLen = GR_GL_INIT_ZERO;
475 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
476 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
478 // retrieve length even though we don't need it to workaround
479 // bug in chrome cmd buffer param validation.
480 GrGLsizei length = GR_GL_INIT_ZERO;
481 GL_CALL(GetProgramInfoLog(programID,
485 SkDebugf((char*)log.get());
487 SkDEBUGFAIL("Error linking program");
488 GL_CALL(DeleteProgram(programID));
491 return SkToBool(linked);
494 void GrGLProgramBuilder::resolveUniformLocations(GrGLuint programID) {
495 int count = fUniforms.count();
496 for (int i = 0; i < count; ++i) {
498 GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariable.c_str()));
499 fUniforms[i].fLocation = location;
503 void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) {
504 GL_CALL(DeleteProgram(programID));
505 cleanupShaders(shaderIDs);
507 void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
508 for (int i = 0; i < shaderIDs.count(); ++i) {
509 GL_CALL(DeleteShader(shaderIDs[i]));
513 GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
514 return SkNEW_ARGS(GrGLProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms,
515 fGeometryProcessor, fFragmentProcessors.get()));
518 ///////////////////////////////////////////////////////////////////////////////////////////////////
520 GrGLInstalledFragProcs::~GrGLInstalledFragProcs() {
521 int numProcs = fProcs.count();
522 for (int e = 0; e < numProcs; ++e) {