blob: 28d15174238d8ad198cc6a3dee39866cb2ef4a8a [file] [log] [blame]
joshualitt30ba4362014-08-21 20:18:45 -07001/*
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
joshualitt47bb3822014-10-07 16:43:25 -07008#include "GrGLProgramBuilder.h"
joshualitt30ba4362014-08-21 20:18:45 -07009#include "gl/GrGLProgram.h"
10#include "gl/GrGLSLPrettyPrint.h"
11#include "gl/GrGLUniformHandle.h"
joshualittdb0d3ca2014-10-07 12:42:26 -070012#include "../GrGpuGL.h"
joshualitt47bb3822014-10-07 16:43:25 -070013#include "GrCoordTransform.h"
14#include "GrGLLegacyNvprProgramBuilder.h"
15#include "GrGLNvprProgramBuilder.h"
joshualitt30ba4362014-08-21 20:18:45 -070016#include "GrGLProgramBuilder.h"
17#include "GrTexture.h"
joshualitt30ba4362014-08-21 20:18:45 -070018#include "SkRTConf.h"
19#include "SkTraceEvent.h"
20
joshualitt30ba4362014-08-21 20:18:45 -070021#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)
23
joshualitt30ba4362014-08-21 20:18:45 -070024// ES2 FS only guarantees mediump and lowp support
25static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision;
joshualitt30ba4362014-08-21 20:18:45 -070026
27//////////////////////////////////////////////////////////////////////////////
28
joshualitt47bb3822014-10-07 16:43:25 -070029const int GrGLProgramBuilder::kVarsPerBlock = 8;
30
31GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState,
32 const GrGLProgramDesc& desc,
33 GrGpu::DrawType drawType,
joshualitt47bb3822014-10-07 16:43:25 -070034 GrGpuGL* gpu) {
35 // create a builder. This will be handed off to effects so they can use it to add
36 // uniforms, varyings, textures, etc
37 SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(desc,
38 optState,
39 drawType,
joshualitta5305a12014-10-10 17:47:00 -070040 optState.hasGeometryProcessor(),
joshualitt47bb3822014-10-07 16:43:25 -070041 gpu));
42
43 GrGLProgramBuilder* pb = builder.get();
44 const GrGLProgramDesc::KeyHeader& header = pb->header();
45
46 // emit code to read the dst copy texture, if necessary
47 if (GrGLFragmentShaderBuilder::kNoDstRead_DstReadKey != header.fDstReadKey
48 && !gpu->glCaps().fbFetchSupport()) {
49 pb->fFS.emitCodeToReadDstTexture();
50 }
51
52 // get the initial color and coverage to feed into the first effect in each effect chain
53 GrGLSLExpr4 inputColor, inputCoverage;
54 pb->setupUniformColorAndCoverageIfNeeded(&inputColor, &inputCoverage);
55
56 // if we have a vertex shader(we don't only if we are using NVPR or NVPR ES), then we may have
57 // to setup a few more things like builtin vertex attributes
58 bool hasVertexShader = !header.fUseFragShaderOnly;
59 if (hasVertexShader) {
60 pb->fVS.setupLocalCoords();
61 pb->fVS.transformGLToSkiaCoords();
62 if (header.fEmitsPointSize) {
63 pb->fVS.codeAppend("gl_PointSize = 1.0;");
64 }
65 if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) {
66 pb->fVS.setupBuiltinVertexAttribute("Color", &inputColor);
67 }
68 if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) {
69 pb->fVS.setupBuiltinVertexAttribute("Coverage", &inputCoverage);
70 }
71 }
72
joshualitta5305a12014-10-10 17:47:00 -070073 pb->emitAndInstallProcs(optState, &inputColor, &inputCoverage);
joshualitt47bb3822014-10-07 16:43:25 -070074
75 if (hasVertexShader) {
76 pb->fVS.transformSkiaToGLCoords();
77 }
78
79 // write the secondary color output if necessary
80 if (GrOptDrawState::kNone_SecondaryOutputType != header.fSecondaryOutputType) {
81 pb->fFS.enableSecondaryOutput(inputColor, inputCoverage);
82 }
83
84 pb->fFS.combineColorAndCoverage(inputColor, inputCoverage);
85
86 return pb->finalize();
87}
88
89GrGLProgramBuilder*
90GrGLProgramBuilder::CreateProgramBuilder(const GrGLProgramDesc& desc,
91 const GrOptDrawState& optState,
92 GrGpu::DrawType drawType,
93 bool hasGeometryProcessor,
94 GrGpuGL* gpu) {
95 if (desc.getHeader().fUseFragShaderOnly) {
96 SkASSERT(gpu->glCaps().pathRenderingSupport());
97 SkASSERT(gpu->glPathRendering()->texturingMode() ==
98 GrGLPathRendering::FixedFunction_TexturingMode);
99 SkASSERT(!hasGeometryProcessor);
100 return SkNEW_ARGS(GrGLLegacyNvprProgramBuilder, (gpu, optState, desc));
101 } else if (GrGpu::IsPathRenderingDrawType(drawType)) {
102 SkASSERT(gpu->glCaps().pathRenderingSupport());
103 SkASSERT(gpu->glPathRendering()->texturingMode() ==
104 GrGLPathRendering::SeparableShaders_TexturingMode);
105 SkASSERT(!hasGeometryProcessor);
106 return SkNEW_ARGS(GrGLNvprProgramBuilder, (gpu, optState, desc));
107 } else {
108 return SkNEW_ARGS(GrGLProgramBuilder, (gpu, optState, desc));
109 }
110}
111
112/////////////////////////////////////////////////////////////////////////////
113
joshualitta5305a12014-10-10 17:47:00 -0700114GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu,
115 const GrOptDrawState& optState,
joshualitt30ba4362014-08-21 20:18:45 -0700116 const GrGLProgramDesc& desc)
joshualitt47bb3822014-10-07 16:43:25 -0700117 : fVS(this)
118 , fGS(this)
joshualitt30ba4362014-08-21 20:18:45 -0700119 , fFS(this, desc)
joshualitt47bb3822014-10-07 16:43:25 -0700120 , fOutOfStage(true)
121 , fStageIndex(-1)
joshualitta5305a12014-10-10 17:47:00 -0700122 , fGeometryProcessor(NULL)
egdaniel307796b2014-10-06 12:13:54 -0700123 , fOptState(optState)
joshualitt30ba4362014-08-21 20:18:45 -0700124 , fDesc(desc)
125 , fGpu(gpu)
126 , fUniforms(kVarsPerBlock) {
127}
128
joshualitt74077b92014-10-24 11:26:03 -0700129void GrGLProgramBuilder::addVarying(const char* name,
130 GrGLVarying* varying,
joshualitt47bb3822014-10-07 16:43:25 -0700131 GrGLShaderVar::Precision fsPrecision) {
joshualitt74077b92014-10-24 11:26:03 -0700132 SkASSERT(varying);
133 if (varying->vsVarying()) {
134 fVS.addVarying(name, varying);
135 }
136 if (fOptState.hasGeometryProcessor() && fOptState.getGeometryProcessor()->willUseGeoShader()) {
137 fGS.addVarying(name, varying);
138 }
139 if (varying->fsVarying()) {
140 fFS.addVarying(varying, fsPrecision);
141 }
joshualitt47bb3822014-10-07 16:43:25 -0700142}
143
joshualitt30ba4362014-08-21 20:18:45 -0700144void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name) {
145 if ('\0' == prefix) {
146 *out = name;
147 } else {
148 out->printf("%c%s", prefix, name);
149 }
joshualitt47bb3822014-10-07 16:43:25 -0700150 if (!fOutOfStage) {
joshualitt30ba4362014-08-21 20:18:45 -0700151 if (out->endsWith('_')) {
152 // Names containing "__" are reserved.
153 out->append("x");
154 }
joshualitt47bb3822014-10-07 16:43:25 -0700155 out->appendf("_Stage%d", fStageIndex);
joshualitt30ba4362014-08-21 20:18:45 -0700156 }
157}
158
159GrGLProgramDataManager::UniformHandle GrGLProgramBuilder::addUniformArray(uint32_t visibility,
160 GrSLType type,
161 const char* name,
162 int count,
163 const char** outName) {
164 SkASSERT(name && strlen(name));
165 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFragment_Visibility);
166 SkASSERT(0 == (~kVisibilityMask & visibility));
167 SkASSERT(0 != visibility);
168
169 UniformInfo& uni = fUniforms.push_back();
170 uni.fVariable.setType(type);
171 uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
172 this->nameVariable(uni.fVariable.accessName(), 'u', name);
173 uni.fVariable.setArrayCount(count);
174 uni.fVisibility = visibility;
175
176 // If it is visible in both the VS and FS, the precision must match.
177 // We declare a default FS precision, but not a default VS. So set the var
178 // to use the default FS precision.
179 if ((kVertex_Visibility | kFragment_Visibility) == visibility) {
180 // the fragment and vertex precisions must match
181 uni.fVariable.setPrecision(kDefaultFragmentPrecision);
182 }
183
bsalomon49f085d2014-09-05 13:34:00 -0700184 if (outName) {
joshualitt30ba4362014-08-21 20:18:45 -0700185 *outName = uni.fVariable.c_str();
186 }
187 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fUniforms.count() - 1);
188}
189
joshualitt30ba4362014-08-21 20:18:45 -0700190void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility,
191 SkString* out) const {
192 for (int i = 0; i < fUniforms.count(); ++i) {
193 if (fUniforms[i].fVisibility & visibility) {
194 fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out);
195 out->append(";\n");
196 }
197 }
198}
199
joshualitt47bb3822014-10-07 16:43:25 -0700200const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const {
201 return fGpu->ctxInfo();
202}
203
204void GrGLProgramBuilder::setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor,
205 GrGLSLExpr4* inputCoverage) {
206 const GrGLProgramDesc::KeyHeader& header = this->header();
207 if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) {
208 const char* name;
209 fUniformHandles.fColorUni =
210 this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
211 kVec4f_GrSLType,
212 "Color",
213 &name);
214 *inputColor = GrGLSLExpr4(name);
215 } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fColorInput) {
216 *inputColor = GrGLSLExpr4(1);
217 }
218 if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) {
219 const char* name;
220 fUniformHandles.fCoverageUni =
221 this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
222 kVec4f_GrSLType,
223 "Coverage",
224 &name);
225 *inputCoverage = GrGLSLExpr4(name);
226 } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) {
227 *inputCoverage = GrGLSLExpr4(1);
228 }
229}
230
joshualitta5305a12014-10-10 17:47:00 -0700231void GrGLProgramBuilder::emitAndInstallProcs(const GrOptDrawState& optState,
232 GrGLSLExpr4* inputColor,
233 GrGLSLExpr4* inputCoverage) {
234 fFragmentProcessors.reset(SkNEW(GrGLInstalledFragProcs));
235 int numProcs = optState.numFragmentStages();
236 this->emitAndInstallFragProcs(0, optState.numColorStages(), inputColor);
237 if (optState.hasGeometryProcessor()) {
238 const GrGeometryProcessor& gp = *optState.getGeometryProcessor();
239 fVS.emitAttributes(gp);
240 ProcKeyProvider keyProvider(&fDesc, ProcKeyProvider::kGeometry_ProcessorType);
241 GrGLSLExpr4 output;
242 this->emitAndInstallProc<GrGeometryProcessor>(gp, 0, keyProvider, *inputCoverage, &output);
243 *inputCoverage = output;
joshualitt47bb3822014-10-07 16:43:25 -0700244 }
joshualitta5305a12014-10-10 17:47:00 -0700245 this->emitAndInstallFragProcs(optState.numColorStages(), numProcs, inputCoverage);
joshualitt47bb3822014-10-07 16:43:25 -0700246}
247
joshualitta5305a12014-10-10 17:47:00 -0700248void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut) {
249 ProcKeyProvider keyProvider(&fDesc, ProcKeyProvider::kFragment_ProcessorType);
250 for (int e = procOffset; e < numProcs; ++e) {
251 GrGLSLExpr4 output;
252 const GrFragmentStage& stage = fOptState.getFragmentStage(e);
253 this->emitAndInstallProc<GrFragmentStage>(stage, e, keyProvider, *inOut, &output);
254 *inOut = output;
joshualitt30ba4362014-08-21 20:18:45 -0700255 }
joshualitta5305a12014-10-10 17:47:00 -0700256}
joshualitt30ba4362014-08-21 20:18:45 -0700257
joshualitta5305a12014-10-10 17:47:00 -0700258// TODO Processors cannot output zeros because an empty string is all 1s
259// the fix is to allow effects to take the GrGLSLExpr4 directly
260template <class Proc>
261void GrGLProgramBuilder::emitAndInstallProc(const Proc& proc,
262 int index,
263 const ProcKeyProvider keyProvider,
264 const GrGLSLExpr4& input,
265 GrGLSLExpr4* output) {
266 // Program builders have a bit of state we need to clear with each effect
267 AutoStageAdvance adv(this);
268
269 // create var to hold stage result
270 SkString outColorName;
271 this->nameVariable(&outColorName, '\0', "output");
272 fFS.codeAppendf("vec4 %s;", outColorName.c_str());
273 *output = outColorName;
274
275 // Enclose custom code in a block to avoid namespace conflicts
276 SkString openBrace;
277 openBrace.printf("{ // Stage %d\n", fStageIndex);
278 fFS.codeAppend(openBrace.c_str());
279
280 this->emitAndInstallProc(proc, keyProvider.get(index), output->c_str(),
281 input.isOnes() ? NULL : input.c_str());
282
283 fFS.codeAppend("}");
284}
285
286void GrGLProgramBuilder::emitAndInstallProc(const GrFragmentStage& fs,
287 const GrProcessorKey& key,
288 const char* outColor,
289 const char* inColor) {
290 GrGLInstalledFragProc* ifp = SkNEW_ARGS(GrGLInstalledFragProc, (fVS.hasLocalCoords()));
291
292 const GrFragmentProcessor& fp = *fs.getProcessor();
293 ifp->fGLProc.reset(fp.getFactory().createGLInstance(fp));
294
295 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(fp.numTextures());
296 this->emitSamplers(fp, &samplers, ifp);
297
298 // Fragment processors can have coord transforms
299 SkSTArray<2, GrGLProcessor::TransformedCoords> coords(fp.numTransforms());
300 this->emitTransforms(fs, &coords, ifp);
301
302 ifp->fGLProc->emitCode(this, fp, key, outColor, inColor, coords, samplers);
303
304 // We have to check that effects and the code they emit are consistent, ie if an effect
305 // asks for dst color, then the emit code needs to follow suit
306 verify(fp);
307 fFragmentProcessors->fProcs.push_back(ifp);
308}
309
310void GrGLProgramBuilder::emitAndInstallProc(const GrGeometryProcessor& gp,
311 const GrProcessorKey& key,
312 const char* outColor,
313 const char* inColor) {
314 SkASSERT(!fGeometryProcessor);
315 fGeometryProcessor = SkNEW(GrGLInstalledGeoProc);
316
317 fGeometryProcessor->fGLProc.reset(gp.getFactory().createGLInstance(gp));
318
319 SkSTArray<4, GrGLProcessor::TextureSampler> samplers(gp.numTextures());
320 this->emitSamplers(gp, &samplers, fGeometryProcessor);
321
joshualittc369e7c2014-10-22 10:56:26 -0700322 GrGLGeometryProcessor::EmitArgs args(this, gp, key, outColor, inColor, samplers);
323 fGeometryProcessor->fGLProc->emitCode(args);
joshualitta5305a12014-10-10 17:47:00 -0700324
325 // We have to check that effects and the code they emit are consistent, ie if an effect
326 // asks for dst color, then the emit code needs to follow suit
327 verify(gp);
joshualitt30ba4362014-08-21 20:18:45 -0700328}
329
joshualitt47bb3822014-10-07 16:43:25 -0700330void GrGLProgramBuilder::verify(const GrGeometryProcessor& gp) {
331 SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition());
joshualittfe1233c2014-10-07 12:16:35 -0700332}
333
joshualitt47bb3822014-10-07 16:43:25 -0700334void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) {
335 SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition());
336 SkASSERT(fFS.hasReadDstColor() == fp.willReadDstColor());
337}
338
joshualitta5305a12014-10-10 17:47:00 -0700339void GrGLProgramBuilder::emitTransforms(const GrFragmentStage& effectStage,
joshualitt47bb3822014-10-07 16:43:25 -0700340 GrGLProcessor::TransformedCoordsArray* outCoords,
joshualitta5305a12014-10-10 17:47:00 -0700341 GrGLInstalledFragProc* ifp) {
342 const GrFragmentProcessor* effect = effectStage.getProcessor();
joshualitt47bb3822014-10-07 16:43:25 -0700343 int numTransforms = effect->numTransforms();
joshualitta5305a12014-10-10 17:47:00 -0700344 ifp->fTransforms.push_back_n(numTransforms);
joshualitt47bb3822014-10-07 16:43:25 -0700345
346 for (int t = 0; t < numTransforms; t++) {
347 const char* uniName = "StageMatrix";
348 GrSLType varyingType =
joshualitta5305a12014-10-10 17:47:00 -0700349 effectStage.isPerspectiveCoordTransform(t, fVS.hasLocalCoords()) ?
joshualitt47bb3822014-10-07 16:43:25 -0700350 kVec3f_GrSLType :
351 kVec2f_GrSLType;
352
353 SkString suffixedUniName;
354 if (0 != t) {
355 suffixedUniName.append(uniName);
356 suffixedUniName.appendf("_%i", t);
357 uniName = suffixedUniName.c_str();
358 }
joshualitta5305a12014-10-10 17:47:00 -0700359 ifp->fTransforms[t].fHandle = this->addUniform(GrGLProgramBuilder::kVertex_Visibility,
360 kMat33f_GrSLType,
361 uniName,
362 &uniName).toShaderBuilderIndex();
joshualitt47bb3822014-10-07 16:43:25 -0700363
364 const char* varyingName = "MatrixCoord";
365 SkString suffixedVaryingName;
366 if (0 != t) {
367 suffixedVaryingName.append(varyingName);
368 suffixedVaryingName.appendf("_%i", t);
369 varyingName = suffixedVaryingName.c_str();
370 }
joshualitt74077b92014-10-24 11:26:03 -0700371 GrGLVertToFrag v(varyingType);
372 this->addVarying(varyingName, &v);
joshualitt47bb3822014-10-07 16:43:25 -0700373
374 const GrGLShaderVar& coords =
375 kPosition_GrCoordSet == effect->coordTransform(t).sourceCoords() ?
376 fVS.positionAttribute() :
377 fVS.localCoordsAttribute();
378
379 // varying = matrix * coords (logically)
380 SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
381 if (kVec2f_GrSLType == varyingType) {
382 fVS.codeAppendf("%s = (%s * vec3(%s, 1)).xy;",
joshualitt74077b92014-10-24 11:26:03 -0700383 v.vsOut(), uniName, coords.c_str());
joshualitt47bb3822014-10-07 16:43:25 -0700384 } else {
385 fVS.codeAppendf("%s = %s * vec3(%s, 1);",
joshualitt74077b92014-10-24 11:26:03 -0700386 v.vsOut(), uniName, coords.c_str());
joshualitt47bb3822014-10-07 16:43:25 -0700387 }
388 SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords,
joshualitt74077b92014-10-24 11:26:03 -0700389 (SkString(v.fsIn()), varyingType));
joshualitt47bb3822014-10-07 16:43:25 -0700390 }
391}
392
393void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor,
394 GrGLProcessor::TextureSamplerArray* outSamplers,
joshualitta5305a12014-10-10 17:47:00 -0700395 GrGLInstalledProc* ip) {
joshualitt47bb3822014-10-07 16:43:25 -0700396 int numTextures = processor.numTextures();
joshualitta5305a12014-10-10 17:47:00 -0700397 ip->fSamplers.push_back_n(numTextures);
joshualitt23e280d2014-09-18 12:26:38 -0700398 SkString name;
399 for (int t = 0; t < numTextures; ++t) {
400 name.printf("Sampler%d", t);
joshualitta5305a12014-10-10 17:47:00 -0700401 ip->fSamplers[t].fUniform = this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
402 kSampler2D_GrSLType,
403 name.c_str());
joshualittb0a8a372014-09-23 09:50:21 -0700404 SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLProcessor::TextureSampler,
joshualitta5305a12014-10-10 17:47:00 -0700405 (ip->fSamplers[t].fUniform, processor.textureAccess(t)));
joshualitt23e280d2014-09-18 12:26:38 -0700406 }
407}
408
joshualitt47bb3822014-10-07 16:43:25 -0700409GrGLProgram* GrGLProgramBuilder::finalize() {
410 // verify we can get a program id
411 GrGLuint programID;
412 GL_CALL_RET(programID, CreateProgram());
413 if (0 == programID) {
414 return NULL;
joshualitt30ba4362014-08-21 20:18:45 -0700415 }
416
joshualitt47bb3822014-10-07 16:43:25 -0700417 // compile shaders and bind attributes / uniforms
joshualitt30ba4362014-08-21 20:18:45 -0700418 SkTDArray<GrGLuint> shadersToDelete;
joshualitt47bb3822014-10-07 16:43:25 -0700419 if (!fFS.compileAndAttachShaders(programID, &shadersToDelete)) {
420 this->cleanupProgram(programID, shadersToDelete);
421 return NULL;
joshualitt30ba4362014-08-21 20:18:45 -0700422 }
joshualitt47bb3822014-10-07 16:43:25 -0700423 if (!this->header().fUseFragShaderOnly) {
424 if (!fVS.compileAndAttachShaders(programID, &shadersToDelete)) {
425 this->cleanupProgram(programID, shadersToDelete);
426 return NULL;
427 }
428 fVS.bindVertexAttributes(programID);
429 }
430 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
431 if (usingBindUniform) {
432 this->bindUniformLocations(programID);
433 }
434 fFS.bindFragmentShaderLocations(programID);
435 GL_CALL(LinkProgram(programID));
joshualitt30ba4362014-08-21 20:18:45 -0700436
437 // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
438 bool checkLinked = !fGpu->ctxInfo().isChromium();
439#ifdef SK_DEBUG
440 checkLinked = true;
441#endif
442 if (checkLinked) {
joshualitt47bb3822014-10-07 16:43:25 -0700443 checkLinkStatus(programID);
joshualittfe1233c2014-10-07 12:16:35 -0700444 }
joshualittdb0d3ca2014-10-07 12:42:26 -0700445 if (!usingBindUniform) {
joshualitt47bb3822014-10-07 16:43:25 -0700446 this->resolveUniformLocations(programID);
joshualittdb0d3ca2014-10-07 12:42:26 -0700447 }
448
joshualitt47bb3822014-10-07 16:43:25 -0700449 this->cleanupShaders(shadersToDelete);
450
451 return this->createProgram(programID);
452}
453
454void GrGLProgramBuilder::bindUniformLocations(GrGLuint programID) {
455 int count = fUniforms.count();
456 for (int i = 0; i < count; ++i) {
457 GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_str()));
458 fUniforms[i].fLocation = i;
459 }
460}
461
462bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) {
463 GrGLint linked = GR_GL_INIT_ZERO;
464 GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
465 if (!linked) {
466 GrGLint infoLen = GR_GL_INIT_ZERO;
467 GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
468 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
469 if (infoLen > 0) {
470 // retrieve length even though we don't need it to workaround
471 // bug in chrome cmd buffer param validation.
472 GrGLsizei length = GR_GL_INIT_ZERO;
473 GL_CALL(GetProgramInfoLog(programID,
474 infoLen+1,
475 &length,
476 (char*)log.get()));
477 GrPrintf((char*)log.get());
478 }
479 SkDEBUGFAIL("Error linking program");
480 GL_CALL(DeleteProgram(programID));
481 programID = 0;
482 }
483 return SkToBool(linked);
484}
485
486void GrGLProgramBuilder::resolveUniformLocations(GrGLuint programID) {
487 int count = fUniforms.count();
kkinnunenec56e452014-08-25 22:21:16 -0700488 for (int i = 0; i < count; ++i) {
489 GrGLint location;
joshualitt47bb3822014-10-07 16:43:25 -0700490 GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariable.c_str()));
491 fUniforms[i].fLocation = location;
kkinnunenec56e452014-08-25 22:21:16 -0700492 }
joshualitt30ba4362014-08-21 20:18:45 -0700493}
494
joshualitt47bb3822014-10-07 16:43:25 -0700495void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) {
496 GL_CALL(DeleteProgram(programID));
497 cleanupShaders(shaderIDs);
498}
499void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
500 for (int i = 0; i < shaderIDs.count(); ++i) {
501 GL_CALL(DeleteShader(shaderIDs[i]));
502 }
503}
504
505GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
506 return SkNEW_ARGS(GrGLProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms,
joshualitta5305a12014-10-10 17:47:00 -0700507 fGeometryProcessor, fFragmentProcessors.get()));
joshualitt47bb3822014-10-07 16:43:25 -0700508}
509
joshualitta5305a12014-10-10 17:47:00 -0700510///////////////////////////////////////////////////////////////////////////////////////////////////
joshualitt47bb3822014-10-07 16:43:25 -0700511
joshualitta5305a12014-10-10 17:47:00 -0700512GrGLInstalledFragProcs::~GrGLInstalledFragProcs() {
513 int numProcs = fProcs.count();
514 for (int e = 0; e < numProcs; ++e) {
515 SkDELETE(fProcs[e]);
joshualitt47bb3822014-10-07 16:43:25 -0700516 }
joshualitt30ba4362014-08-21 20:18:45 -0700517}