blob: 3691fe994b3977a633947fd0a393a840b059fbb4 [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)
42, fUniformManager(gpu) {
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000043 fDesc = desc;
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000044 fProgramID = 0;
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000045
bsalomon@google.com804e9942013-06-06 18:04:38 +000046 fDstCopyTexUnit = -1;
47
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000048 fColor = GrColor_ILLEGAL;
49 fColorFilterColor = GrColor_ILLEGAL;
50
bsalomon@google.com2c84aa32013-06-06 20:28:57 +000051 this->genProgram(colorStages, coverageStages);
junov@google.comf93e7172011-03-31 21:26:24 +000052}
53
54GrGLProgram::~GrGLProgram() {
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000055 if (fProgramID) {
56 GL_CALL(DeleteProgram(fProgramID));
57 }
junov@google.comf93e7172011-03-31 21:26:24 +000058}
59
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000060void GrGLProgram::abandon() {
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000061 fProgramID = 0;
62}
63
tomhudson@google.com0d3f1fb2011-06-01 19:27:31 +000064void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff,
bsalomon@google.com271cffc2011-05-20 14:13:56 +000065 GrBlendCoeff* dstCoeff) const {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +000066 switch (fDesc.getHeader().fCoverageOutput) {
bsalomon@google.com5920ac22013-04-19 13:14:45 +000067 case GrGLProgramDesc::kModulate_CoverageOutput:
bsalomon@google.com271cffc2011-05-20 14:13:56 +000068 break;
bsalomon@google.com5920ac22013-04-19 13:14:45 +000069 // The prog will write a coverage value to the secondary
bsalomon@google.com271cffc2011-05-20 14:13:56 +000070 // output and the dst is blended by one minus that value.
bsalomon@google.com5920ac22013-04-19 13:14:45 +000071 case GrGLProgramDesc::kSecondaryCoverage_CoverageOutput:
72 case GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput:
73 case GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput:
74 *dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
75 break;
76 case GrGLProgramDesc::kCombineWithDst_CoverageOutput:
77 // We should only have set this if the blend was specified as (1, 0)
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000078 SkASSERT(kOne_GrBlendCoeff == *srcCoeff && kZero_GrBlendCoeff == *dstCoeff);
bsalomon@google.com5920ac22013-04-19 13:14:45 +000079 break;
bsalomon@google.com271cffc2011-05-20 14:13:56 +000080 default:
bsalomon@google.com5920ac22013-04-19 13:14:45 +000081 GrCrash("Unexpected coverage output");
bsalomon@google.com271cffc2011-05-20 14:13:56 +000082 break;
83 }
84}
85
bsalomon@google.com34cccde2013-01-04 18:34:30 +000086namespace {
bsalomon@google.com5920ac22013-04-19 13:14:45 +000087// given two blend coefficients determine whether the src
bsalomon@google.comf2d91552011-05-16 20:56:06 +000088// and/or dst computation can be omitted.
bsalomon@google.com34cccde2013-01-04 18:34:30 +000089inline void need_blend_inputs(SkXfermode::Coeff srcCoeff,
90 SkXfermode::Coeff dstCoeff,
91 bool* needSrcValue,
92 bool* needDstValue) {
bsalomon@google.comf2d91552011-05-16 20:56:06 +000093 if (SkXfermode::kZero_Coeff == srcCoeff) {
94 switch (dstCoeff) {
95 // these all read the src
96 case SkXfermode::kSC_Coeff:
97 case SkXfermode::kISC_Coeff:
98 case SkXfermode::kSA_Coeff:
99 case SkXfermode::kISA_Coeff:
100 *needSrcValue = true;
101 break;
102 default:
103 *needSrcValue = false;
104 break;
105 }
106 } else {
107 *needSrcValue = true;
108 }
109 if (SkXfermode::kZero_Coeff == dstCoeff) {
110 switch (srcCoeff) {
111 // these all read the dst
112 case SkXfermode::kDC_Coeff:
113 case SkXfermode::kIDC_Coeff:
114 case SkXfermode::kDA_Coeff:
115 case SkXfermode::kIDA_Coeff:
116 *needDstValue = true;
117 break;
118 default:
119 *needDstValue = false;
120 break;
121 }
122 } else {
123 *needDstValue = true;
Scroggo97c88c22011-05-11 14:05:25 +0000124 }
125}
126
127/**
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000128 * Create a blend_coeff * value string to be used in shader code. Sets empty
129 * string if result is trivially zero.
130 */
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000131inline void blend_term_string(SkString* str, SkXfermode::Coeff coeff,
132 const char* src, const char* dst,
133 const char* value) {
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000134 switch (coeff) {
135 case SkXfermode::kZero_Coeff: /** 0 */
136 *str = "";
137 break;
138 case SkXfermode::kOne_Coeff: /** 1 */
139 *str = value;
140 break;
141 case SkXfermode::kSC_Coeff:
142 str->printf("(%s * %s)", src, value);
143 break;
144 case SkXfermode::kISC_Coeff:
bsalomon@google.com4af0af62012-08-29 12:59:57 +0000145 str->printf("((%s - %s) * %s)", GrGLSLOnesVecf(4), src, value);
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000146 break;
147 case SkXfermode::kDC_Coeff:
148 str->printf("(%s * %s)", dst, value);
149 break;
150 case SkXfermode::kIDC_Coeff:
bsalomon@google.com4af0af62012-08-29 12:59:57 +0000151 str->printf("((%s - %s) * %s)", GrGLSLOnesVecf(4), dst, value);
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000152 break;
153 case SkXfermode::kSA_Coeff: /** src alpha */
154 str->printf("(%s.a * %s)", src, value);
155 break;
156 case SkXfermode::kISA_Coeff: /** inverse src alpha (i.e. 1 - sa) */
157 str->printf("((1.0 - %s.a) * %s)", src, value);
158 break;
159 case SkXfermode::kDA_Coeff: /** dst alpha */
160 str->printf("(%s.a * %s)", dst, value);
161 break;
162 case SkXfermode::kIDA_Coeff: /** inverse dst alpha (i.e. 1 - da) */
163 str->printf("((1.0 - %s.a) * %s)", dst, value);
164 break;
165 default:
166 GrCrash("Unexpected xfer coeff.");
167 break;
168 }
169}
170/**
Scroggo97c88c22011-05-11 14:05:25 +0000171 * Adds a line to the fragment shader code which modifies the color by
172 * the specified color filter.
173 */
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000174void add_color_filter(GrGLShaderBuilder* builder,
175 const char * outputVar,
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000176 SkXfermode::Coeff uniformCoeff,
177 SkXfermode::Coeff colorCoeff,
178 const char* filterColor,
179 const char* inColor) {
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000180 SkString colorStr, constStr;
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000181 blend_term_string(&colorStr, colorCoeff, filterColor, inColor, inColor);
182 blend_term_string(&constStr, uniformCoeff, filterColor, inColor, filterColor);
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000183
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000184 SkString sum;
bsalomon@google.com018f1792013-04-18 19:36:09 +0000185 GrGLSLAddf<4>(&sum, colorStr.c_str(), constStr.c_str());
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000186 builder->fsCodeAppendf("\t%s = %s;\n", outputVar, sum.c_str());
Scroggo97c88c22011-05-11 14:05:25 +0000187}
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000188}
Scroggo97c88c22011-05-11 14:05:25 +0000189
bsalomon@google.comad5e9372012-07-11 18:11:27 +0000190namespace {
bsalomon@google.comad5e9372012-07-11 18:11:27 +0000191
bsalomon@google.com5920ac22013-04-19 13:14:45 +0000192void expand_known_value4f(SkString* string, GrSLConstantVec vec) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000193 SkASSERT(string->isEmpty() == (vec != kNone_GrSLConstantVec));
bsalomon@google.com5920ac22013-04-19 13:14:45 +0000194 switch (vec) {
195 case kNone_GrSLConstantVec:
196 break;
197 case kZeros_GrSLConstantVec:
198 *string = GrGLSLZerosVecf(4);
199 break;
200 case kOnes_GrSLConstantVec:
201 *string = GrGLSLOnesVecf(4);
202 break;
203 }
204}
205
bsalomon@google.com9ba4fa62012-07-16 17:36:28 +0000206}
207
bsalomon@google.com2c84aa32013-06-06 20:28:57 +0000208bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
209 const GrEffectStage* coverageStages[]) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000210 SkASSERT(0 == fProgramID);
bsalomon@google.comecb60aa2012-07-18 13:20:29 +0000211
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000212 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
213
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000214 bool needsVertexShader = true;
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000215
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000216 GrGLShaderBuilder builder(fGpu, fUniformManager, fDesc, needsVertexShader);
commit-bot@chromium.org5a02cb42013-08-30 20:17:31 +0000217 if (GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder.getVertexBuilder()) {
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000218 fUniformHandles.fViewMatrixUni = vertexBuilder->getViewMatrixUniform();
bsalomon@google.come55fd0f2012-02-10 15:56:06 +0000219 }
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000220
bsalomon@google.com91961302011-05-09 18:39:58 +0000221 // incoming color to current stage being processed.
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000222 SkString inColor = builder.getInputColor();
223 GrSLConstantVec knownColorValue = builder.getKnownColorValue();
junov@google.comf93e7172011-03-31 21:26:24 +0000224
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000225 // Get the coeffs for the Mode-based color filter, determine if color is needed.
226 SkXfermode::Coeff colorCoeff;
227 SkXfermode::Coeff filterColorCoeff;
228 SkAssertResult(
commit-bot@chromium.org949eef02013-10-01 18:43:29 +0000229 SkXfermode::ModeAsCoeff(header.fColorFilterXfermode,
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000230 &filterColorCoeff,
231 &colorCoeff));
232 bool needColor, needFilterColor;
233 need_blend_inputs(filterColorCoeff, colorCoeff, &needFilterColor, &needColor);
234
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000235 fColorEffects.reset(
236 builder.createAndEmitEffects(colorStages,
237 fDesc.effectKeys(),
238 needColor ? fDesc.numColorEffects() : 0,
239 &inColor,
240 &knownColorValue));
Scroggo97c88c22011-05-11 14:05:25 +0000241
bsalomon@google.com018f1792013-04-18 19:36:09 +0000242 // Insert the color filter. This will soon be replaced by a color effect.
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000243 if (SkXfermode::kDst_Mode != header.fColorFilterXfermode) {
bsalomon@google.com018f1792013-04-18 19:36:09 +0000244 const char* colorFilterColorUniName = NULL;
commit-bot@chromium.org74a3a212013-08-30 19:43:59 +0000245 fUniformHandles.fColorFilterUni = builder.addUniform(GrGLShaderBuilder::kFragment_Visibility,
bsalomon@google.com018f1792013-04-18 19:36:09 +0000246 kVec4f_GrSLType, "FilterColor",
247 &colorFilterColorUniName);
248
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000249 builder.fsCodeAppend("\tvec4 filteredColor;\n");
bsalomon@google.com018f1792013-04-18 19:36:09 +0000250 const char* color;
251 // add_color_filter requires a real input string.
252 if (knownColorValue == kOnes_GrSLConstantVec) {
253 color = GrGLSLOnesVecf(4);
254 } else if (knownColorValue == kZeros_GrSLConstantVec) {
255 color = GrGLSLZerosVecf(4);
256 } else {
257 color = inColor.c_str();
258 }
259 add_color_filter(&builder, "filteredColor", filterColorCoeff,
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000260 colorCoeff, colorFilterColorUniName, color);
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000261 inColor = "filteredColor";
262 }
263
264 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com018f1792013-04-18 19:36:09 +0000265 // compute the partial coverage
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000266 SkString inCoverage = builder.getInputCoverage();
267 GrSLConstantVec knownCoverageValue = builder.getKnownCoverageValue();
skia.committer@gmail.comcb6dc752013-04-19 07:01:00 +0000268
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000269 fCoverageEffects.reset(
270 builder.createAndEmitEffects(coverageStages,
271 fDesc.getEffectKeys() + fDesc.numColorEffects(),
272 fDesc.numCoverageEffects(),
273 &inCoverage,
274 &knownCoverageValue));
bsalomon@google.com504976e2013-05-09 13:45:02 +0000275
bsalomon@google.com018f1792013-04-18 19:36:09 +0000276 // discard if coverage is zero
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000277 if (header.fDiscardIfZeroCoverage && kOnes_GrSLConstantVec != knownCoverageValue) {
bsalomon@google.com018f1792013-04-18 19:36:09 +0000278 if (kZeros_GrSLConstantVec == knownCoverageValue) {
279 // This is unfortunate.
280 builder.fsCodeAppend("\tdiscard;\n");
281 } else {
282 builder.fsCodeAppendf("\tif (all(lessThanEqual(%s, vec4(0.0)))) {\n\t\tdiscard;\n\t}\n",
283 inCoverage.c_str());
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000284 }
junov@google.comf93e7172011-03-31 21:26:24 +0000285 }
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000286
commit-bot@chromium.org949eef02013-10-01 18:43:29 +0000287 if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(header.fCoverageOutput)) {
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000288 const char* secondaryOutputName = builder.enableSecondaryOutput();
289
bsalomon@google.com018f1792013-04-18 19:36:09 +0000290 // default coeff to ones for kCoverage_DualSrcOutput
291 SkString coeff;
292 GrSLConstantVec knownCoeffValue = kOnes_GrSLConstantVec;
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000293 if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCoverageOutput) {
bsalomon@google.com018f1792013-04-18 19:36:09 +0000294 // Get (1-A) into coeff
295 SkString inColorAlpha;
296 GrGLSLGetComponent4f(&inColorAlpha,
297 inColor.c_str(),
298 kA_GrColorComponentFlag,
299 knownColorValue,
300 true);
301 knownCoeffValue = GrGLSLSubtractf<1>(&coeff,
302 NULL,
303 inColorAlpha.c_str(),
304 kOnes_GrSLConstantVec,
305 knownColorValue,
306 true);
commit-bot@chromium.org949eef02013-10-01 18:43:29 +0000307 } else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput == header.fCoverageOutput) {
bsalomon@google.com018f1792013-04-18 19:36:09 +0000308 // Get (1-RGBA) into coeff
309 knownCoeffValue = GrGLSLSubtractf<4>(&coeff,
310 NULL,
311 inColor.c_str(),
312 kOnes_GrSLConstantVec,
313 knownColorValue,
314 true);
315 }
316 // Get coeff * coverage into modulate and then write that to the dual source output.
317 SkString modulate;
318 GrGLSLModulatef<4>(&modulate,
319 coeff.c_str(),
320 inCoverage.c_str(),
321 knownCoeffValue,
322 knownCoverageValue,
323 false);
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000324 builder.fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, modulate.c_str());
bsalomon@google.com018f1792013-04-18 19:36:09 +0000325 }
326
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000327 ///////////////////////////////////////////////////////////////////////////
328 // combine color and coverage as frag color
329
bsalomon@google.com5920ac22013-04-19 13:14:45 +0000330 // Get "color * coverage" into fragColor
331 SkString fragColor;
332 GrSLConstantVec knownFragColorValue = GrGLSLModulatef<4>(&fragColor,
333 inColor.c_str(),
334 inCoverage.c_str(),
335 knownColorValue,
336 knownCoverageValue,
337 true);
338 // 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 +0000339 if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == header.fCoverageOutput) {
bsalomon@google.com5920ac22013-04-19 13:14:45 +0000340 SkString dstCoeff;
341 GrSLConstantVec knownDstCoeffValue = GrGLSLSubtractf<4>(&dstCoeff,
342 NULL,
343 inCoverage.c_str(),
344 kOnes_GrSLConstantVec,
345 knownCoverageValue,
346 true);
347 SkString dstContribution;
348 GrSLConstantVec knownDstContributionValue = GrGLSLModulatef<4>(&dstContribution,
349 dstCoeff.c_str(),
350 builder.dstColor(),
351 knownDstCoeffValue,
352 kNone_GrSLConstantVec,
353 true);
354 SkString oldFragColor = fragColor;
355 fragColor.reset();
356 GrGLSLAddf<4>(&fragColor,
357 oldFragColor.c_str(),
358 dstContribution.c_str(),
359 knownFragColorValue,
360 knownDstContributionValue,
361 false);
362 } else {
363 expand_known_value4f(&fragColor, knownFragColorValue);
364 }
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000365 builder.fsCodeAppendf("\t%s = %s;\n", builder.getColorOutputName(), fragColor.c_str());
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000366
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000367 if (!builder.finish(&fProgramID)) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000368 return false;
369 }
370
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000371 fUniformHandles.fRTHeightUni = builder.getRTHeightUniform();
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000372 fUniformHandles.fDstCopyTopLeftUni = builder.getDstCopyTopLeftUniform();
373 fUniformHandles.fDstCopyScaleUni = builder.getDstCopyScaleUniform();
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000374 fUniformHandles.fColorUni = builder.getColorUniform();
375 fUniformHandles.fCoverageUni = builder.getCoverageUniform();
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000376 fUniformHandles.fDstCopySamplerUni = builder.getDstCopySamplerUniform();
377 // This must be called after we set fDstCopySamplerUni above.
378 this->initSamplerUniforms();
bsalomon@google.com91961302011-05-09 18:39:58 +0000379
380 return true;
381}
382
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000383void GrGLProgram::initSamplerUniforms() {
bsalomon@google.com9ba4fa62012-07-16 17:36:28 +0000384 GL_CALL(UseProgram(fProgramID));
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000385 GrGLint texUnitIdx = 0;
commit-bot@chromium.org7425c122013-08-14 18:14:19 +0000386 if (fUniformHandles.fDstCopySamplerUni.isValid()) {
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000387 fUniformManager.setSampler(fUniformHandles.fDstCopySamplerUni, texUnitIdx);
bsalomon@google.com804e9942013-06-06 18:04:38 +0000388 fDstCopyTexUnit = texUnitIdx++;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000389 }
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000390 fColorEffects->initSamplers(fUniformManager, &texUnitIdx);
391 fCoverageEffects->initSamplers(fUniformManager, &texUnitIdx);
bsalomon@google.com91961302011-05-09 18:39:58 +0000392}
393
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000394///////////////////////////////////////////////////////////////////////////////
junov@google.comf93e7172011-03-31 21:26:24 +0000395
commit-bot@chromium.org9188a152013-09-05 18:28:24 +0000396void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts,
bsalomon@google.com2c84aa32013-06-06 20:28:57 +0000397 const GrEffectStage* colorStages[],
398 const GrEffectStage* coverageStages[],
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000399 const GrDeviceCoordTexture* dstCopy,
bsalomon@google.com91207482013-02-12 21:45:24 +0000400 SharedGLState* sharedState) {
commit-bot@chromium.org9188a152013-09-05 18:28:24 +0000401 const GrDrawState& drawState = fGpu->getDrawState();
bsalomon@google.com9ba4fa62012-07-16 17:36:28 +0000402
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000403 GrColor color;
404 GrColor coverage;
405 if (blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag) {
406 color = 0;
407 coverage = 0;
408 } else if (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) {
409 color = 0xffffffff;
410 coverage = drawState.getCoverage();
411 } else {
412 color = drawState.getColor();
413 coverage = drawState.getCoverage();
414 }
415
bsalomon@google.com91207482013-02-12 21:45:24 +0000416 this->setColor(drawState, color, sharedState);
417 this->setCoverage(drawState, coverage, sharedState);
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000418 this->setMatrixAndRenderTargetHeight(drawState);
bsalomon@google.com91207482013-02-12 21:45:24 +0000419
420 // Setup the SkXfermode::Mode-based colorfilter uniform if necessary
commit-bot@chromium.org7425c122013-08-14 18:14:19 +0000421 if (fUniformHandles.fColorFilterUni.isValid() &&
bsalomon@google.com91207482013-02-12 21:45:24 +0000422 fColorFilterColor != drawState.getColorFilterColor()) {
423 GrGLfloat c[4];
424 GrColorToRGBAFloat(drawState.getColorFilterColor(), c);
425 fUniformManager.set4fv(fUniformHandles.fColorFilterUni, 0, 1, c);
426 fColorFilterColor = drawState.getColorFilterColor();
427 }
428
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000429 if (NULL != dstCopy) {
commit-bot@chromium.org7425c122013-08-14 18:14:19 +0000430 if (fUniformHandles.fDstCopyTopLeftUni.isValid()) {
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000431 fUniformManager.set2f(fUniformHandles.fDstCopyTopLeftUni,
432 static_cast<GrGLfloat>(dstCopy->offset().fX),
433 static_cast<GrGLfloat>(dstCopy->offset().fY));
434 fUniformManager.set2f(fUniformHandles.fDstCopyScaleUni,
435 1.f / dstCopy->texture()->width(),
436 1.f / dstCopy->texture()->height());
437 GrGLTexture* texture = static_cast<GrGLTexture*>(dstCopy->texture());
438 static GrTextureParams kParams; // the default is clamp, nearest filtering.
commit-bot@chromium.org9188a152013-09-05 18:28:24 +0000439 fGpu->bindTexture(fDstCopyTexUnit, kParams, texture);
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000440 } else {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000441 SkASSERT(!fUniformHandles.fDstCopyScaleUni.isValid());
442 SkASSERT(!fUniformHandles.fDstCopySamplerUni.isValid());
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000443 }
444 } else {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000445 SkASSERT(!fUniformHandles.fDstCopyTopLeftUni.isValid());
446 SkASSERT(!fUniformHandles.fDstCopyScaleUni.isValid());
447 SkASSERT(!fUniformHandles.fDstCopySamplerUni.isValid());
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000448 }
bsalomon@google.comc7818882013-03-20 19:19:53 +0000449
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000450 fColorEffects->setData(fGpu, fUniformManager, colorStages);
451 fCoverageEffects->setData(fGpu, fUniformManager, coverageStages);
skia.committer@gmail.com8ae714b2013-01-05 02:02:05 +0000452}
bsalomon@google.com91207482013-02-12 21:45:24 +0000453
454void GrGLProgram::setColor(const GrDrawState& drawState,
455 GrColor color,
456 SharedGLState* sharedState) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000457 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
jvanverth@google.com054ae992013-04-01 20:06:51 +0000458 if (!drawState.hasColorVertexAttribute()) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000459 switch (header.fColorInput) {
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000460 case GrGLProgramDesc::kAttribute_ColorInput:
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000461 SkASSERT(-1 != header.fColorAttributeIndex);
jvanverth@google.com054ae992013-04-01 20:06:51 +0000462 if (sharedState->fConstAttribColor != color ||
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000463 sharedState->fConstAttribColorIndex != header.fColorAttributeIndex) {
bsalomon@google.com91207482013-02-12 21:45:24 +0000464 // OpenGL ES only supports the float varieties of glVertexAttrib
465 GrGLfloat c[4];
466 GrColorToRGBAFloat(color, c);
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000467 GL_CALL(VertexAttrib4fv(header.fColorAttributeIndex, c));
bsalomon@google.com91207482013-02-12 21:45:24 +0000468 sharedState->fConstAttribColor = color;
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000469 sharedState->fConstAttribColorIndex = header.fColorAttributeIndex;
bsalomon@google.com91207482013-02-12 21:45:24 +0000470 }
471 break;
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000472 case GrGLProgramDesc::kUniform_ColorInput:
bsalomon@google.com91207482013-02-12 21:45:24 +0000473 if (fColor != color) {
474 // OpenGL ES doesn't support unsigned byte varieties of glUniform
475 GrGLfloat c[4];
476 GrColorToRGBAFloat(color, c);
bsalomon@google.com91207482013-02-12 21:45:24 +0000477 fUniformManager.set4fv(fUniformHandles.fColorUni, 0, 1, c);
478 fColor = color;
479 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000480 sharedState->fConstAttribColorIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000481 break;
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000482 case GrGLProgramDesc::kSolidWhite_ColorInput:
483 case GrGLProgramDesc::kTransBlack_ColorInput:
jvanverth@google.com054ae992013-04-01 20:06:51 +0000484 sharedState->fConstAttribColorIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000485 break;
486 default:
487 GrCrash("Unknown color type.");
488 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000489 } else {
490 sharedState->fConstAttribColorIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000491 }
492}
493
494void GrGLProgram::setCoverage(const GrDrawState& drawState,
495 GrColor coverage,
496 SharedGLState* sharedState) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000497 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
jvanverth@google.com054ae992013-04-01 20:06:51 +0000498 if (!drawState.hasCoverageVertexAttribute()) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000499 switch (header.fCoverageInput) {
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000500 case GrGLProgramDesc::kAttribute_ColorInput:
jvanverth@google.com054ae992013-04-01 20:06:51 +0000501 if (sharedState->fConstAttribCoverage != coverage ||
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000502 sharedState->fConstAttribCoverageIndex != header.fCoverageAttributeIndex) {
bsalomon@google.com91207482013-02-12 21:45:24 +0000503 // OpenGL ES only supports the float varieties of glVertexAttrib
504 GrGLfloat c[4];
505 GrColorToRGBAFloat(coverage, c);
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000506 GL_CALL(VertexAttrib4fv(header.fCoverageAttributeIndex, c));
bsalomon@google.com91207482013-02-12 21:45:24 +0000507 sharedState->fConstAttribCoverage = coverage;
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000508 sharedState->fConstAttribCoverageIndex = header.fCoverageAttributeIndex;
bsalomon@google.com91207482013-02-12 21:45:24 +0000509 }
510 break;
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000511 case GrGLProgramDesc::kUniform_ColorInput:
bsalomon@google.com91207482013-02-12 21:45:24 +0000512 if (fCoverage != coverage) {
513 // OpenGL ES doesn't support unsigned byte varieties of glUniform
514 GrGLfloat c[4];
515 GrColorToRGBAFloat(coverage, c);
bsalomon@google.com91207482013-02-12 21:45:24 +0000516 fUniformManager.set4fv(fUniformHandles.fCoverageUni, 0, 1, c);
517 fCoverage = coverage;
518 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000519 sharedState->fConstAttribCoverageIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000520 break;
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000521 case GrGLProgramDesc::kSolidWhite_ColorInput:
522 case GrGLProgramDesc::kTransBlack_ColorInput:
jvanverth@google.com054ae992013-04-01 20:06:51 +0000523 sharedState->fConstAttribCoverageIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000524 break;
525 default:
526 GrCrash("Unknown coverage type.");
527 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000528 } else {
529 sharedState->fConstAttribCoverageIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000530 }
531}
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000532
533void GrGLProgram::setMatrixAndRenderTargetHeight(const GrDrawState& drawState) {
534 const GrRenderTarget* rt = drawState.getRenderTarget();
535 SkISize size;
536 size.set(rt->width(), rt->height());
537
538 // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
commit-bot@chromium.org7425c122013-08-14 18:14:19 +0000539 if (fUniformHandles.fRTHeightUni.isValid() &&
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000540 fMatrixState.fRenderTargetSize.fHeight != size.fHeight) {
541 fUniformManager.set1f(fUniformHandles.fRTHeightUni, SkIntToScalar(size.fHeight));
542 }
543
544 if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
545 !fMatrixState.fViewMatrix.cheapEqualTo(drawState.getViewMatrix()) ||
546 fMatrixState.fRenderTargetSize != size) {
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000547
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000548 fMatrixState.fViewMatrix = drawState.getViewMatrix();
549 fMatrixState.fRenderTargetSize = size;
550 fMatrixState.fRenderTargetOrigin = rt->origin();
commit-bot@chromium.org215a6822013-09-05 18:28:42 +0000551
552 GrGLfloat viewMatrix[3 * 3];
553 fMatrixState.getGLMatrix<3>(viewMatrix);
554 fUniformManager.setMatrix3f(fUniformHandles.fViewMatrixUni, viewMatrix);
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000555 }
556}