blob: 1ca61e374883b1d3f9292ae8a4c34c5aea96e2ef [file] [log] [blame]
junov@google.comf93e7172011-03-31 21:26:24 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * 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.
junov@google.comf93e7172011-03-31 21:26:24 +00006 */
7
8#include "GrGLProgram.h"
9
tomhudson@google.comd8f856c2012-05-10 12:13:36 +000010#include "GrAllocator.h"
bsalomon@google.coma469c282012-10-24 18:28:34 +000011#include "GrEffect.h"
bsalomon@google.com77af6802013-10-02 13:04:56 +000012#include "GrCoordTransform.h"
bsalomon@google.comc7818882013-03-20 19:19:53 +000013#include "GrDrawEffect.h"
bsalomon@google.comd698f772012-10-25 13:22:00 +000014#include "GrGLEffect.h"
bsalomon@google.com34cccde2013-01-04 18:34:30 +000015#include "GrGpuGL.h"
bsalomon@google.com4fa66942011-09-20 19:06:12 +000016#include "GrGLShaderVar.h"
bsalomon@google.com018f1792013-04-18 19:36:09 +000017#include "GrGLSL.h"
Scroggo97c88c22011-05-11 14:05:25 +000018#include "SkXfermode.h"
19
bsalomon@google.com9ba4fa62012-07-16 17:36:28 +000020SK_DEFINE_INST_COUNT(GrGLProgram)
21
commit-bot@chromium.org9188a152013-09-05 18:28:24 +000022#define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
23#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X)
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000024
commit-bot@chromium.org9188a152013-09-05 18:28:24 +000025GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu,
bsalomon@google.com31ec7982013-03-27 18:14:57 +000026 const GrGLProgramDesc& desc,
bsalomon@google.com2c84aa32013-06-06 20:28:57 +000027 const GrEffectStage* colorStages[],
28 const GrEffectStage* coverageStages[]) {
commit-bot@chromium.org9188a152013-09-05 18:28:24 +000029 GrGLProgram* program = SkNEW_ARGS(GrGLProgram, (gpu, desc, colorStages, coverageStages));
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000030 if (!program->succeeded()) {
31 delete program;
32 program = NULL;
33 }
34 return program;
35}
36
commit-bot@chromium.org9188a152013-09-05 18:28:24 +000037GrGLProgram::GrGLProgram(GrGpuGL* gpu,
bsalomon@google.com31ec7982013-03-27 18:14:57 +000038 const GrGLProgramDesc& desc,
bsalomon@google.com2c84aa32013-06-06 20:28:57 +000039 const GrEffectStage* colorStages[],
40 const GrEffectStage* coverageStages[])
commit-bot@chromium.org9188a152013-09-05 18:28:24 +000041: fGpu(gpu)
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000042, fUniformManager(gpu)
43, fHasVertexShader(false)
44, fNumTexCoordSets(0) {
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000045 fDesc = desc;
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000046 fProgramID = 0;
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000047
bsalomon@google.com804e9942013-06-06 18:04:38 +000048 fDstCopyTexUnit = -1;
49
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000050 fColor = GrColor_ILLEGAL;
51 fColorFilterColor = GrColor_ILLEGAL;
52
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000053 if (fDesc.getHeader().fHasVertexCode ||
54 !fGpu->glCaps().fixedFunctionSupport() ||
55 !fGpu->glCaps().pathStencilingSupport()) {
56
57 GrGLFullShaderBuilder fullBuilder(fGpu, fUniformManager, fDesc);
58 if (this->genProgram(&fullBuilder, colorStages, coverageStages)) {
59 fUniformHandles.fViewMatrixUni = fullBuilder.getViewMatrixUniform();
60 fHasVertexShader = true;
61 }
62 } else {
63 GrGLFragmentOnlyShaderBuilder fragmentOnlyBuilder(fGpu, fUniformManager, fDesc);
64 if (this->genProgram(&fragmentOnlyBuilder, colorStages, coverageStages)) {
65 fNumTexCoordSets = fragmentOnlyBuilder.getNumTexCoordSets();
66 }
67 }
junov@google.comf93e7172011-03-31 21:26:24 +000068}
69
70GrGLProgram::~GrGLProgram() {
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000071 if (fProgramID) {
72 GL_CALL(DeleteProgram(fProgramID));
73 }
junov@google.comf93e7172011-03-31 21:26:24 +000074}
75
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000076void GrGLProgram::abandon() {
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000077 fProgramID = 0;
78}
79
tomhudson@google.com0d3f1fb2011-06-01 19:27:31 +000080void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff,
bsalomon@google.com271cffc2011-05-20 14:13:56 +000081 GrBlendCoeff* dstCoeff) const {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +000082 switch (fDesc.getHeader().fCoverageOutput) {
bsalomon@google.com5920ac22013-04-19 13:14:45 +000083 case GrGLProgramDesc::kModulate_CoverageOutput:
bsalomon@google.com271cffc2011-05-20 14:13:56 +000084 break;
bsalomon@google.com5920ac22013-04-19 13:14:45 +000085 // The prog will write a coverage value to the secondary
bsalomon@google.com271cffc2011-05-20 14:13:56 +000086 // output and the dst is blended by one minus that value.
bsalomon@google.com5920ac22013-04-19 13:14:45 +000087 case GrGLProgramDesc::kSecondaryCoverage_CoverageOutput:
88 case GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput:
89 case GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput:
90 *dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
91 break;
92 case GrGLProgramDesc::kCombineWithDst_CoverageOutput:
93 // We should only have set this if the blend was specified as (1, 0)
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000094 SkASSERT(kOne_GrBlendCoeff == *srcCoeff && kZero_GrBlendCoeff == *dstCoeff);
bsalomon@google.com5920ac22013-04-19 13:14:45 +000095 break;
bsalomon@google.com271cffc2011-05-20 14:13:56 +000096 default:
bsalomon@google.com5920ac22013-04-19 13:14:45 +000097 GrCrash("Unexpected coverage output");
bsalomon@google.com271cffc2011-05-20 14:13:56 +000098 break;
99 }
100}
101
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000102namespace {
bsalomon@google.com5920ac22013-04-19 13:14:45 +0000103// given two blend coefficients determine whether the src
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000104// and/or dst computation can be omitted.
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000105inline void need_blend_inputs(SkXfermode::Coeff srcCoeff,
106 SkXfermode::Coeff dstCoeff,
107 bool* needSrcValue,
108 bool* needDstValue) {
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000109 if (SkXfermode::kZero_Coeff == srcCoeff) {
110 switch (dstCoeff) {
111 // these all read the src
112 case SkXfermode::kSC_Coeff:
113 case SkXfermode::kISC_Coeff:
114 case SkXfermode::kSA_Coeff:
115 case SkXfermode::kISA_Coeff:
116 *needSrcValue = true;
117 break;
118 default:
119 *needSrcValue = false;
120 break;
121 }
122 } else {
123 *needSrcValue = true;
124 }
125 if (SkXfermode::kZero_Coeff == dstCoeff) {
126 switch (srcCoeff) {
127 // these all read the dst
128 case SkXfermode::kDC_Coeff:
129 case SkXfermode::kIDC_Coeff:
130 case SkXfermode::kDA_Coeff:
131 case SkXfermode::kIDA_Coeff:
132 *needDstValue = true;
133 break;
134 default:
135 *needDstValue = false;
136 break;
137 }
138 } else {
139 *needDstValue = true;
Scroggo97c88c22011-05-11 14:05:25 +0000140 }
141}
142
143/**
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000144 * Create a blend_coeff * value string to be used in shader code. Sets empty
145 * string if result is trivially zero.
146 */
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000147inline void blend_term_string(SkString* str, SkXfermode::Coeff coeff,
148 const char* src, const char* dst,
149 const char* value) {
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000150 switch (coeff) {
151 case SkXfermode::kZero_Coeff: /** 0 */
152 *str = "";
153 break;
154 case SkXfermode::kOne_Coeff: /** 1 */
155 *str = value;
156 break;
157 case SkXfermode::kSC_Coeff:
158 str->printf("(%s * %s)", src, value);
159 break;
160 case SkXfermode::kISC_Coeff:
bsalomon@google.com4af0af62012-08-29 12:59:57 +0000161 str->printf("((%s - %s) * %s)", GrGLSLOnesVecf(4), src, value);
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000162 break;
163 case SkXfermode::kDC_Coeff:
164 str->printf("(%s * %s)", dst, value);
165 break;
166 case SkXfermode::kIDC_Coeff:
bsalomon@google.com4af0af62012-08-29 12:59:57 +0000167 str->printf("((%s - %s) * %s)", GrGLSLOnesVecf(4), dst, value);
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000168 break;
169 case SkXfermode::kSA_Coeff: /** src alpha */
170 str->printf("(%s.a * %s)", src, value);
171 break;
172 case SkXfermode::kISA_Coeff: /** inverse src alpha (i.e. 1 - sa) */
173 str->printf("((1.0 - %s.a) * %s)", src, value);
174 break;
175 case SkXfermode::kDA_Coeff: /** dst alpha */
176 str->printf("(%s.a * %s)", dst, value);
177 break;
178 case SkXfermode::kIDA_Coeff: /** inverse dst alpha (i.e. 1 - da) */
179 str->printf("((1.0 - %s.a) * %s)", dst, value);
180 break;
181 default:
182 GrCrash("Unexpected xfer coeff.");
183 break;
184 }
185}
186/**
Scroggo97c88c22011-05-11 14:05:25 +0000187 * Adds a line to the fragment shader code which modifies the color by
188 * the specified color filter.
189 */
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000190void add_color_filter(GrGLShaderBuilder* builder,
191 const char * outputVar,
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000192 SkXfermode::Coeff uniformCoeff,
193 SkXfermode::Coeff colorCoeff,
194 const char* filterColor,
195 const char* inColor) {
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000196 SkString colorStr, constStr;
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000197 blend_term_string(&colorStr, colorCoeff, filterColor, inColor, inColor);
198 blend_term_string(&constStr, uniformCoeff, filterColor, inColor, filterColor);
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000199
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000200 SkString sum;
bsalomon@google.com018f1792013-04-18 19:36:09 +0000201 GrGLSLAddf<4>(&sum, colorStr.c_str(), constStr.c_str());
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000202 builder->fsCodeAppendf("\t%s = %s;\n", outputVar, sum.c_str());
Scroggo97c88c22011-05-11 14:05:25 +0000203}
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000204}
Scroggo97c88c22011-05-11 14:05:25 +0000205
bsalomon@google.comad5e9372012-07-11 18:11:27 +0000206namespace {
bsalomon@google.comad5e9372012-07-11 18:11:27 +0000207
bsalomon@google.com5920ac22013-04-19 13:14:45 +0000208void expand_known_value4f(SkString* string, GrSLConstantVec vec) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000209 SkASSERT(string->isEmpty() == (vec != kNone_GrSLConstantVec));
bsalomon@google.com5920ac22013-04-19 13:14:45 +0000210 switch (vec) {
211 case kNone_GrSLConstantVec:
212 break;
213 case kZeros_GrSLConstantVec:
214 *string = GrGLSLZerosVecf(4);
215 break;
216 case kOnes_GrSLConstantVec:
217 *string = GrGLSLOnesVecf(4);
218 break;
219 }
220}
221
bsalomon@google.com9ba4fa62012-07-16 17:36:28 +0000222}
223
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000224bool GrGLProgram::genProgram(GrGLShaderBuilder* builder,
225 const GrEffectStage* colorStages[],
bsalomon@google.com2c84aa32013-06-06 20:28:57 +0000226 const GrEffectStage* coverageStages[]) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000227 SkASSERT(0 == fProgramID);
bsalomon@google.comecb60aa2012-07-18 13:20:29 +0000228
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000229 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
230
bsalomon@google.com91961302011-05-09 18:39:58 +0000231 // incoming color to current stage being processed.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000232 SkString inColor = builder->getInputColor();
233 GrSLConstantVec knownColorValue = builder->getKnownColorValue();
junov@google.comf93e7172011-03-31 21:26:24 +0000234
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000235 // Get the coeffs for the Mode-based color filter, determine if color is needed.
236 SkXfermode::Coeff colorCoeff;
237 SkXfermode::Coeff filterColorCoeff;
238 SkAssertResult(
commit-bot@chromium.org949eef02013-10-01 18:43:29 +0000239 SkXfermode::ModeAsCoeff(header.fColorFilterXfermode,
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000240 &filterColorCoeff,
241 &colorCoeff));
242 bool needColor, needFilterColor;
243 need_blend_inputs(filterColorCoeff, colorCoeff, &needFilterColor, &needColor);
244
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000245 fColorEffects.reset(
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000246 builder->createAndEmitEffects(colorStages,
247 fDesc.effectKeys(),
248 needColor ? fDesc.numColorEffects() : 0,
249 &inColor,
250 &knownColorValue));
Scroggo97c88c22011-05-11 14:05:25 +0000251
bsalomon@google.com018f1792013-04-18 19:36:09 +0000252 // Insert the color filter. This will soon be replaced by a color effect.
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000253 if (SkXfermode::kDst_Mode != header.fColorFilterXfermode) {
bsalomon@google.com018f1792013-04-18 19:36:09 +0000254 const char* colorFilterColorUniName = NULL;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000255 fUniformHandles.fColorFilterUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
256 kVec4f_GrSLType, "FilterColor",
257 &colorFilterColorUniName);
bsalomon@google.com018f1792013-04-18 19:36:09 +0000258
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000259 builder->fsCodeAppend("\tvec4 filteredColor;\n");
bsalomon@google.com018f1792013-04-18 19:36:09 +0000260 const char* color;
261 // add_color_filter requires a real input string.
262 if (knownColorValue == kOnes_GrSLConstantVec) {
263 color = GrGLSLOnesVecf(4);
264 } else if (knownColorValue == kZeros_GrSLConstantVec) {
265 color = GrGLSLZerosVecf(4);
266 } else {
267 color = inColor.c_str();
268 }
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000269 add_color_filter(builder, "filteredColor", filterColorCoeff,
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000270 colorCoeff, colorFilterColorUniName, color);
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000271 inColor = "filteredColor";
272 }
273
274 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com018f1792013-04-18 19:36:09 +0000275 // compute the partial coverage
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000276 SkString inCoverage = builder->getInputCoverage();
277 GrSLConstantVec knownCoverageValue = builder->getKnownCoverageValue();
skia.committer@gmail.comcb6dc752013-04-19 07:01:00 +0000278
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000279 fCoverageEffects.reset(
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000280 builder->createAndEmitEffects(coverageStages,
281 fDesc.getEffectKeys() + fDesc.numColorEffects(),
282 fDesc.numCoverageEffects(),
283 &inCoverage,
284 &knownCoverageValue));
bsalomon@google.com504976e2013-05-09 13:45:02 +0000285
bsalomon@google.com018f1792013-04-18 19:36:09 +0000286 // discard if coverage is zero
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000287 if (header.fDiscardIfZeroCoverage && kOnes_GrSLConstantVec != knownCoverageValue) {
bsalomon@google.com018f1792013-04-18 19:36:09 +0000288 if (kZeros_GrSLConstantVec == knownCoverageValue) {
289 // This is unfortunate.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000290 builder->fsCodeAppend("\tdiscard;\n");
bsalomon@google.com018f1792013-04-18 19:36:09 +0000291 } else {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000292 builder->fsCodeAppendf("\tif (all(lessThanEqual(%s, vec4(0.0)))) {\n\t\tdiscard;\n\t}\n",
293 inCoverage.c_str());
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000294 }
junov@google.comf93e7172011-03-31 21:26:24 +0000295 }
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000296
commit-bot@chromium.org949eef02013-10-01 18:43:29 +0000297 if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(header.fCoverageOutput)) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000298 const char* secondaryOutputName = builder->enableSecondaryOutput();
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000299
bsalomon@google.com018f1792013-04-18 19:36:09 +0000300 // default coeff to ones for kCoverage_DualSrcOutput
301 SkString coeff;
302 GrSLConstantVec knownCoeffValue = kOnes_GrSLConstantVec;
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000303 if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCoverageOutput) {
bsalomon@google.com018f1792013-04-18 19:36:09 +0000304 // Get (1-A) into coeff
305 SkString inColorAlpha;
306 GrGLSLGetComponent4f(&inColorAlpha,
307 inColor.c_str(),
308 kA_GrColorComponentFlag,
309 knownColorValue,
310 true);
311 knownCoeffValue = GrGLSLSubtractf<1>(&coeff,
312 NULL,
313 inColorAlpha.c_str(),
314 kOnes_GrSLConstantVec,
315 knownColorValue,
316 true);
commit-bot@chromium.org949eef02013-10-01 18:43:29 +0000317 } else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput == header.fCoverageOutput) {
bsalomon@google.com018f1792013-04-18 19:36:09 +0000318 // Get (1-RGBA) into coeff
319 knownCoeffValue = GrGLSLSubtractf<4>(&coeff,
320 NULL,
321 inColor.c_str(),
322 kOnes_GrSLConstantVec,
323 knownColorValue,
324 true);
325 }
326 // Get coeff * coverage into modulate and then write that to the dual source output.
327 SkString modulate;
328 GrGLSLModulatef<4>(&modulate,
329 coeff.c_str(),
330 inCoverage.c_str(),
331 knownCoeffValue,
332 knownCoverageValue,
333 false);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000334 builder->fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, modulate.c_str());
bsalomon@google.com018f1792013-04-18 19:36:09 +0000335 }
336
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000337 ///////////////////////////////////////////////////////////////////////////
338 // combine color and coverage as frag color
339
bsalomon@google.com5920ac22013-04-19 13:14:45 +0000340 // Get "color * coverage" into fragColor
341 SkString fragColor;
342 GrSLConstantVec knownFragColorValue = GrGLSLModulatef<4>(&fragColor,
343 inColor.c_str(),
344 inCoverage.c_str(),
345 knownColorValue,
346 knownCoverageValue,
347 true);
348 // Now tack on "+(1-coverage)dst onto the frag color if we were asked to do so.
commit-bot@chromium.org949eef02013-10-01 18:43:29 +0000349 if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == header.fCoverageOutput) {
bsalomon@google.com5920ac22013-04-19 13:14:45 +0000350 SkString dstCoeff;
351 GrSLConstantVec knownDstCoeffValue = GrGLSLSubtractf<4>(&dstCoeff,
352 NULL,
353 inCoverage.c_str(),
354 kOnes_GrSLConstantVec,
355 knownCoverageValue,
356 true);
357 SkString dstContribution;
358 GrSLConstantVec knownDstContributionValue = GrGLSLModulatef<4>(&dstContribution,
359 dstCoeff.c_str(),
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000360 builder->dstColor(),
bsalomon@google.com5920ac22013-04-19 13:14:45 +0000361 knownDstCoeffValue,
362 kNone_GrSLConstantVec,
363 true);
364 SkString oldFragColor = fragColor;
365 fragColor.reset();
366 GrGLSLAddf<4>(&fragColor,
367 oldFragColor.c_str(),
368 dstContribution.c_str(),
369 knownFragColorValue,
370 knownDstContributionValue,
371 false);
372 } else {
373 expand_known_value4f(&fragColor, knownFragColorValue);
374 }
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000375 builder->fsCodeAppendf("\t%s = %s;\n", builder->getColorOutputName(), fragColor.c_str());
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000376
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000377 if (!builder->finish(&fProgramID)) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000378 return false;
379 }
380
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000381 fUniformHandles.fRTHeightUni = builder->getRTHeightUniform();
382 fUniformHandles.fDstCopyTopLeftUni = builder->getDstCopyTopLeftUniform();
383 fUniformHandles.fDstCopyScaleUni = builder->getDstCopyScaleUniform();
384 fUniformHandles.fColorUni = builder->getColorUniform();
385 fUniformHandles.fCoverageUni = builder->getCoverageUniform();
386 fUniformHandles.fDstCopySamplerUni = builder->getDstCopySamplerUniform();
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000387 // This must be called after we set fDstCopySamplerUni above.
388 this->initSamplerUniforms();
bsalomon@google.com91961302011-05-09 18:39:58 +0000389
390 return true;
391}
392
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000393void GrGLProgram::initSamplerUniforms() {
bsalomon@google.com9ba4fa62012-07-16 17:36:28 +0000394 GL_CALL(UseProgram(fProgramID));
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000395 GrGLint texUnitIdx = 0;
commit-bot@chromium.org7425c122013-08-14 18:14:19 +0000396 if (fUniformHandles.fDstCopySamplerUni.isValid()) {
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000397 fUniformManager.setSampler(fUniformHandles.fDstCopySamplerUni, texUnitIdx);
bsalomon@google.com804e9942013-06-06 18:04:38 +0000398 fDstCopyTexUnit = texUnitIdx++;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000399 }
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000400 fColorEffects->initSamplers(fUniformManager, &texUnitIdx);
401 fCoverageEffects->initSamplers(fUniformManager, &texUnitIdx);
bsalomon@google.com91961302011-05-09 18:39:58 +0000402}
403
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000404///////////////////////////////////////////////////////////////////////////////
junov@google.comf93e7172011-03-31 21:26:24 +0000405
commit-bot@chromium.org9188a152013-09-05 18:28:24 +0000406void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts,
bsalomon@google.com2c84aa32013-06-06 20:28:57 +0000407 const GrEffectStage* colorStages[],
408 const GrEffectStage* coverageStages[],
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000409 const GrDeviceCoordTexture* dstCopy,
bsalomon@google.com91207482013-02-12 21:45:24 +0000410 SharedGLState* sharedState) {
commit-bot@chromium.org9188a152013-09-05 18:28:24 +0000411 const GrDrawState& drawState = fGpu->getDrawState();
bsalomon@google.com9ba4fa62012-07-16 17:36:28 +0000412
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000413 GrColor color;
414 GrColor coverage;
415 if (blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag) {
416 color = 0;
417 coverage = 0;
418 } else if (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) {
419 color = 0xffffffff;
420 coverage = drawState.getCoverage();
421 } else {
422 color = drawState.getColor();
423 coverage = drawState.getCoverage();
424 }
425
bsalomon@google.com91207482013-02-12 21:45:24 +0000426 this->setColor(drawState, color, sharedState);
427 this->setCoverage(drawState, coverage, sharedState);
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000428 this->setMatrixAndRenderTargetHeight(drawState);
bsalomon@google.com91207482013-02-12 21:45:24 +0000429
430 // Setup the SkXfermode::Mode-based colorfilter uniform if necessary
commit-bot@chromium.org7425c122013-08-14 18:14:19 +0000431 if (fUniformHandles.fColorFilterUni.isValid() &&
bsalomon@google.com91207482013-02-12 21:45:24 +0000432 fColorFilterColor != drawState.getColorFilterColor()) {
433 GrGLfloat c[4];
434 GrColorToRGBAFloat(drawState.getColorFilterColor(), c);
435 fUniformManager.set4fv(fUniformHandles.fColorFilterUni, 0, 1, c);
436 fColorFilterColor = drawState.getColorFilterColor();
437 }
438
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000439 if (NULL != dstCopy) {
commit-bot@chromium.org7425c122013-08-14 18:14:19 +0000440 if (fUniformHandles.fDstCopyTopLeftUni.isValid()) {
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000441 fUniformManager.set2f(fUniformHandles.fDstCopyTopLeftUni,
442 static_cast<GrGLfloat>(dstCopy->offset().fX),
443 static_cast<GrGLfloat>(dstCopy->offset().fY));
444 fUniformManager.set2f(fUniformHandles.fDstCopyScaleUni,
445 1.f / dstCopy->texture()->width(),
446 1.f / dstCopy->texture()->height());
447 GrGLTexture* texture = static_cast<GrGLTexture*>(dstCopy->texture());
448 static GrTextureParams kParams; // the default is clamp, nearest filtering.
commit-bot@chromium.org9188a152013-09-05 18:28:24 +0000449 fGpu->bindTexture(fDstCopyTexUnit, kParams, texture);
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000450 } else {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000451 SkASSERT(!fUniformHandles.fDstCopyScaleUni.isValid());
452 SkASSERT(!fUniformHandles.fDstCopySamplerUni.isValid());
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000453 }
454 } else {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000455 SkASSERT(!fUniformHandles.fDstCopyTopLeftUni.isValid());
456 SkASSERT(!fUniformHandles.fDstCopyScaleUni.isValid());
457 SkASSERT(!fUniformHandles.fDstCopySamplerUni.isValid());
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000458 }
bsalomon@google.comc7818882013-03-20 19:19:53 +0000459
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000460 fColorEffects->setData(fGpu, fUniformManager, colorStages);
461 fCoverageEffects->setData(fGpu, fUniformManager, coverageStages);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000462
463 if (!fHasVertexShader) {
464 fGpu->disableUnusedTexGen(fNumTexCoordSets);
465 }
skia.committer@gmail.com8ae714b2013-01-05 02:02:05 +0000466}
bsalomon@google.com91207482013-02-12 21:45:24 +0000467
468void GrGLProgram::setColor(const GrDrawState& drawState,
469 GrColor color,
470 SharedGLState* sharedState) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000471 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
jvanverth@google.com054ae992013-04-01 20:06:51 +0000472 if (!drawState.hasColorVertexAttribute()) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000473 switch (header.fColorInput) {
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000474 case GrGLProgramDesc::kAttribute_ColorInput:
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000475 SkASSERT(-1 != header.fColorAttributeIndex);
jvanverth@google.com054ae992013-04-01 20:06:51 +0000476 if (sharedState->fConstAttribColor != color ||
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000477 sharedState->fConstAttribColorIndex != header.fColorAttributeIndex) {
bsalomon@google.com91207482013-02-12 21:45:24 +0000478 // OpenGL ES only supports the float varieties of glVertexAttrib
479 GrGLfloat c[4];
480 GrColorToRGBAFloat(color, c);
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000481 GL_CALL(VertexAttrib4fv(header.fColorAttributeIndex, c));
bsalomon@google.com91207482013-02-12 21:45:24 +0000482 sharedState->fConstAttribColor = color;
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000483 sharedState->fConstAttribColorIndex = header.fColorAttributeIndex;
bsalomon@google.com91207482013-02-12 21:45:24 +0000484 }
485 break;
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000486 case GrGLProgramDesc::kUniform_ColorInput:
bsalomon@google.com91207482013-02-12 21:45:24 +0000487 if (fColor != color) {
488 // OpenGL ES doesn't support unsigned byte varieties of glUniform
489 GrGLfloat c[4];
490 GrColorToRGBAFloat(color, c);
bsalomon@google.com91207482013-02-12 21:45:24 +0000491 fUniformManager.set4fv(fUniformHandles.fColorUni, 0, 1, c);
492 fColor = color;
493 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000494 sharedState->fConstAttribColorIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000495 break;
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000496 case GrGLProgramDesc::kSolidWhite_ColorInput:
497 case GrGLProgramDesc::kTransBlack_ColorInput:
jvanverth@google.com054ae992013-04-01 20:06:51 +0000498 sharedState->fConstAttribColorIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000499 break;
500 default:
501 GrCrash("Unknown color type.");
502 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000503 } else {
504 sharedState->fConstAttribColorIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000505 }
506}
507
508void GrGLProgram::setCoverage(const GrDrawState& drawState,
509 GrColor coverage,
510 SharedGLState* sharedState) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000511 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
jvanverth@google.com054ae992013-04-01 20:06:51 +0000512 if (!drawState.hasCoverageVertexAttribute()) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000513 switch (header.fCoverageInput) {
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000514 case GrGLProgramDesc::kAttribute_ColorInput:
jvanverth@google.com054ae992013-04-01 20:06:51 +0000515 if (sharedState->fConstAttribCoverage != coverage ||
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000516 sharedState->fConstAttribCoverageIndex != header.fCoverageAttributeIndex) {
bsalomon@google.com91207482013-02-12 21:45:24 +0000517 // OpenGL ES only supports the float varieties of glVertexAttrib
518 GrGLfloat c[4];
519 GrColorToRGBAFloat(coverage, c);
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000520 GL_CALL(VertexAttrib4fv(header.fCoverageAttributeIndex, c));
bsalomon@google.com91207482013-02-12 21:45:24 +0000521 sharedState->fConstAttribCoverage = coverage;
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000522 sharedState->fConstAttribCoverageIndex = header.fCoverageAttributeIndex;
bsalomon@google.com91207482013-02-12 21:45:24 +0000523 }
524 break;
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000525 case GrGLProgramDesc::kUniform_ColorInput:
bsalomon@google.com91207482013-02-12 21:45:24 +0000526 if (fCoverage != coverage) {
527 // OpenGL ES doesn't support unsigned byte varieties of glUniform
528 GrGLfloat c[4];
529 GrColorToRGBAFloat(coverage, c);
bsalomon@google.com91207482013-02-12 21:45:24 +0000530 fUniformManager.set4fv(fUniformHandles.fCoverageUni, 0, 1, c);
531 fCoverage = coverage;
532 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000533 sharedState->fConstAttribCoverageIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000534 break;
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000535 case GrGLProgramDesc::kSolidWhite_ColorInput:
536 case GrGLProgramDesc::kTransBlack_ColorInput:
jvanverth@google.com054ae992013-04-01 20:06:51 +0000537 sharedState->fConstAttribCoverageIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000538 break;
539 default:
540 GrCrash("Unknown coverage type.");
541 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000542 } else {
543 sharedState->fConstAttribCoverageIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000544 }
545}
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000546
547void GrGLProgram::setMatrixAndRenderTargetHeight(const GrDrawState& drawState) {
548 const GrRenderTarget* rt = drawState.getRenderTarget();
549 SkISize size;
550 size.set(rt->width(), rt->height());
551
552 // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
commit-bot@chromium.org7425c122013-08-14 18:14:19 +0000553 if (fUniformHandles.fRTHeightUni.isValid() &&
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000554 fMatrixState.fRenderTargetSize.fHeight != size.fHeight) {
555 fUniformManager.set1f(fUniformHandles.fRTHeightUni, SkIntToScalar(size.fHeight));
556 }
557
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000558 if (!fHasVertexShader) {
559 SkASSERT(!fUniformHandles.fViewMatrixUni.isValid());
560 fGpu->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin());
561 } else if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
562 fMatrixState.fRenderTargetSize != size ||
563 !fMatrixState.fViewMatrix.cheapEqualTo(drawState.getViewMatrix())) {
564 SkASSERT(fUniformHandles.fViewMatrixUni.isValid());
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000565
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000566 fMatrixState.fViewMatrix = drawState.getViewMatrix();
567 fMatrixState.fRenderTargetSize = size;
568 fMatrixState.fRenderTargetOrigin = rt->origin();
commit-bot@chromium.org215a6822013-09-05 18:28:42 +0000569
570 GrGLfloat viewMatrix[3 * 3];
571 fMatrixState.getGLMatrix<3>(viewMatrix);
572 fUniformManager.setMatrix3f(fUniformHandles.fViewMatrixUni, viewMatrix);
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000573 }
574}