blob: c1b3a31218f7af5082a755346539724c8fe7f20e [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 ||
commit-bot@chromium.org8e919ad2013-10-21 14:48:23 +000054 !fGpu->shouldUseFixedFunctionTexturing()) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +000055 GrGLFullShaderBuilder fullBuilder(fGpu, fUniformManager, fDesc);
56 if (this->genProgram(&fullBuilder, colorStages, coverageStages)) {
57 fUniformHandles.fViewMatrixUni = fullBuilder.getViewMatrixUniform();
58 fHasVertexShader = true;
59 }
60 } else {
61 GrGLFragmentOnlyShaderBuilder fragmentOnlyBuilder(fGpu, fUniformManager, fDesc);
62 if (this->genProgram(&fragmentOnlyBuilder, colorStages, coverageStages)) {
63 fNumTexCoordSets = fragmentOnlyBuilder.getNumTexCoordSets();
64 }
65 }
junov@google.comf93e7172011-03-31 21:26:24 +000066}
67
68GrGLProgram::~GrGLProgram() {
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000069 if (fProgramID) {
70 GL_CALL(DeleteProgram(fProgramID));
71 }
junov@google.comf93e7172011-03-31 21:26:24 +000072}
73
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000074void GrGLProgram::abandon() {
bsalomon@google.comecb60aa2012-07-18 13:20:29 +000075 fProgramID = 0;
76}
77
tomhudson@google.com0d3f1fb2011-06-01 19:27:31 +000078void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff,
bsalomon@google.com271cffc2011-05-20 14:13:56 +000079 GrBlendCoeff* dstCoeff) const {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +000080 switch (fDesc.getHeader().fCoverageOutput) {
bsalomon@google.com5920ac22013-04-19 13:14:45 +000081 case GrGLProgramDesc::kModulate_CoverageOutput:
bsalomon@google.com271cffc2011-05-20 14:13:56 +000082 break;
bsalomon@google.com5920ac22013-04-19 13:14:45 +000083 // The prog will write a coverage value to the secondary
bsalomon@google.com271cffc2011-05-20 14:13:56 +000084 // output and the dst is blended by one minus that value.
bsalomon@google.com5920ac22013-04-19 13:14:45 +000085 case GrGLProgramDesc::kSecondaryCoverage_CoverageOutput:
86 case GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput:
87 case GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput:
88 *dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
89 break;
90 case GrGLProgramDesc::kCombineWithDst_CoverageOutput:
91 // We should only have set this if the blend was specified as (1, 0)
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000092 SkASSERT(kOne_GrBlendCoeff == *srcCoeff && kZero_GrBlendCoeff == *dstCoeff);
bsalomon@google.com5920ac22013-04-19 13:14:45 +000093 break;
bsalomon@google.com271cffc2011-05-20 14:13:56 +000094 default:
bsalomon@google.com5920ac22013-04-19 13:14:45 +000095 GrCrash("Unexpected coverage output");
bsalomon@google.com271cffc2011-05-20 14:13:56 +000096 break;
97 }
98}
99
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000100namespace {
bsalomon@google.com5920ac22013-04-19 13:14:45 +0000101// given two blend coefficients determine whether the src
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000102// and/or dst computation can be omitted.
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000103inline void need_blend_inputs(SkXfermode::Coeff srcCoeff,
104 SkXfermode::Coeff dstCoeff,
105 bool* needSrcValue,
106 bool* needDstValue) {
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000107 if (SkXfermode::kZero_Coeff == srcCoeff) {
108 switch (dstCoeff) {
109 // these all read the src
110 case SkXfermode::kSC_Coeff:
111 case SkXfermode::kISC_Coeff:
112 case SkXfermode::kSA_Coeff:
113 case SkXfermode::kISA_Coeff:
114 *needSrcValue = true;
115 break;
116 default:
117 *needSrcValue = false;
118 break;
119 }
120 } else {
121 *needSrcValue = true;
122 }
123 if (SkXfermode::kZero_Coeff == dstCoeff) {
124 switch (srcCoeff) {
125 // these all read the dst
126 case SkXfermode::kDC_Coeff:
127 case SkXfermode::kIDC_Coeff:
128 case SkXfermode::kDA_Coeff:
129 case SkXfermode::kIDA_Coeff:
130 *needDstValue = true;
131 break;
132 default:
133 *needDstValue = false;
134 break;
135 }
136 } else {
137 *needDstValue = true;
Scroggo97c88c22011-05-11 14:05:25 +0000138 }
139}
140
141/**
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000142 * Create a blend_coeff * value string to be used in shader code. Sets empty
143 * string if result is trivially zero.
144 */
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000145inline void blend_term_string(SkString* str, SkXfermode::Coeff coeff,
146 const char* src, const char* dst,
147 const char* value) {
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000148 switch (coeff) {
149 case SkXfermode::kZero_Coeff: /** 0 */
150 *str = "";
151 break;
152 case SkXfermode::kOne_Coeff: /** 1 */
153 *str = value;
154 break;
155 case SkXfermode::kSC_Coeff:
156 str->printf("(%s * %s)", src, value);
157 break;
158 case SkXfermode::kISC_Coeff:
commit-bot@chromium.org824c3462013-10-10 06:30:18 +0000159 str->printf("((vec4(1) - %s) * %s)", src, value);
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000160 break;
161 case SkXfermode::kDC_Coeff:
162 str->printf("(%s * %s)", dst, value);
163 break;
164 case SkXfermode::kIDC_Coeff:
commit-bot@chromium.org824c3462013-10-10 06:30:18 +0000165 str->printf("((vec4(1) - %s) * %s)", dst, value);
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000166 break;
167 case SkXfermode::kSA_Coeff: /** src alpha */
168 str->printf("(%s.a * %s)", src, value);
169 break;
170 case SkXfermode::kISA_Coeff: /** inverse src alpha (i.e. 1 - sa) */
171 str->printf("((1.0 - %s.a) * %s)", src, value);
172 break;
173 case SkXfermode::kDA_Coeff: /** dst alpha */
174 str->printf("(%s.a * %s)", dst, value);
175 break;
176 case SkXfermode::kIDA_Coeff: /** inverse dst alpha (i.e. 1 - da) */
177 str->printf("((1.0 - %s.a) * %s)", dst, value);
178 break;
179 default:
180 GrCrash("Unexpected xfer coeff.");
181 break;
182 }
183}
184/**
Scroggo97c88c22011-05-11 14:05:25 +0000185 * Adds a line to the fragment shader code which modifies the color by
186 * the specified color filter.
187 */
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000188void add_color_filter(GrGLShaderBuilder* builder,
189 const char * outputVar,
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000190 SkXfermode::Coeff uniformCoeff,
191 SkXfermode::Coeff colorCoeff,
192 const char* filterColor,
193 const char* inColor) {
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000194 SkString colorStr, constStr;
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000195 blend_term_string(&colorStr, colorCoeff, filterColor, inColor, inColor);
196 blend_term_string(&constStr, uniformCoeff, filterColor, inColor, filterColor);
commit-bot@chromium.org824c3462013-10-10 06:30:18 +0000197 GrGLSLExpr<4> sum;
198 if (colorStr.isEmpty() && constStr.isEmpty()) {
199 sum = GrGLSLExpr<4>(0);
200 } else if (colorStr.isEmpty()) {
201 sum = constStr;
202 } else if (constStr.isEmpty()) {
203 sum = colorStr;
204 } else {
205 sum = GrGLSLExpr<4>(colorStr) + GrGLSLExpr<4>(constStr);
206 }
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000207 builder->fsCodeAppendf("\t%s = %s;\n", outputVar, sum.c_str());
Scroggo97c88c22011-05-11 14:05:25 +0000208}
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000209}
Scroggo97c88c22011-05-11 14:05:25 +0000210
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000211bool GrGLProgram::genProgram(GrGLShaderBuilder* builder,
212 const GrEffectStage* colorStages[],
bsalomon@google.com2c84aa32013-06-06 20:28:57 +0000213 const GrEffectStage* coverageStages[]) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000214 SkASSERT(0 == fProgramID);
bsalomon@google.comecb60aa2012-07-18 13:20:29 +0000215
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000216 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
217
bsalomon@google.com91961302011-05-09 18:39:58 +0000218 // incoming color to current stage being processed.
commit-bot@chromium.org824c3462013-10-10 06:30:18 +0000219 GrGLSLExpr<4> inColor = builder->getInputColor();
junov@google.comf93e7172011-03-31 21:26:24 +0000220
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000221 // Get the coeffs for the Mode-based color filter, determine if color is needed.
222 SkXfermode::Coeff colorCoeff;
223 SkXfermode::Coeff filterColorCoeff;
224 SkAssertResult(
commit-bot@chromium.org949eef02013-10-01 18:43:29 +0000225 SkXfermode::ModeAsCoeff(header.fColorFilterXfermode,
commit-bot@chromium.orga4acf122013-09-30 15:13:58 +0000226 &filterColorCoeff,
227 &colorCoeff));
228 bool needColor, needFilterColor;
229 need_blend_inputs(filterColorCoeff, colorCoeff, &needFilterColor, &needColor);
230
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000231 fColorEffects.reset(
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000232 builder->createAndEmitEffects(colorStages,
233 fDesc.effectKeys(),
234 needColor ? fDesc.numColorEffects() : 0,
commit-bot@chromium.org824c3462013-10-10 06:30:18 +0000235 &inColor));
Scroggo97c88c22011-05-11 14:05:25 +0000236
bsalomon@google.com018f1792013-04-18 19:36:09 +0000237 // Insert the color filter. This will soon be replaced by a color effect.
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000238 if (SkXfermode::kDst_Mode != header.fColorFilterXfermode) {
bsalomon@google.com018f1792013-04-18 19:36:09 +0000239 const char* colorFilterColorUniName = NULL;
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000240 fUniformHandles.fColorFilterUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
241 kVec4f_GrSLType, "FilterColor",
242 &colorFilterColorUniName);
bsalomon@google.com018f1792013-04-18 19:36:09 +0000243
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000244 builder->fsCodeAppend("\tvec4 filteredColor;\n");
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000245 add_color_filter(builder, "filteredColor", filterColorCoeff,
commit-bot@chromium.org824c3462013-10-10 06:30:18 +0000246 colorCoeff, colorFilterColorUniName, inColor.c_str());
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000247 inColor = "filteredColor";
248 }
249
250 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com018f1792013-04-18 19:36:09 +0000251 // compute the partial coverage
commit-bot@chromium.org824c3462013-10-10 06:30:18 +0000252 GrGLSLExpr<4> inCoverage = builder->getInputCoverage();
skia.committer@gmail.comcb6dc752013-04-19 07:01:00 +0000253
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000254 fCoverageEffects.reset(
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000255 builder->createAndEmitEffects(coverageStages,
256 fDesc.getEffectKeys() + fDesc.numColorEffects(),
257 fDesc.numCoverageEffects(),
commit-bot@chromium.org824c3462013-10-10 06:30:18 +0000258 &inCoverage));
bsalomon@google.com504976e2013-05-09 13:45:02 +0000259
bsalomon@google.com018f1792013-04-18 19:36:09 +0000260 // discard if coverage is zero
commit-bot@chromium.org824c3462013-10-10 06:30:18 +0000261 if (header.fDiscardIfZeroCoverage && !inCoverage.isOnes()) {
262 if (inCoverage.isZeros()) {
bsalomon@google.com018f1792013-04-18 19:36:09 +0000263 // This is unfortunate.
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000264 builder->fsCodeAppend("\tdiscard;\n");
bsalomon@google.com018f1792013-04-18 19:36:09 +0000265 } else {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000266 builder->fsCodeAppendf("\tif (all(lessThanEqual(%s, vec4(0.0)))) {\n\t\tdiscard;\n\t}\n",
267 inCoverage.c_str());
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000268 }
junov@google.comf93e7172011-03-31 21:26:24 +0000269 }
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000270
commit-bot@chromium.org949eef02013-10-01 18:43:29 +0000271 if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(header.fCoverageOutput)) {
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000272 const char* secondaryOutputName = builder->enableSecondaryOutput();
commit-bot@chromium.org410552a2013-09-30 15:30:27 +0000273
bsalomon@google.com018f1792013-04-18 19:36:09 +0000274 // default coeff to ones for kCoverage_DualSrcOutput
commit-bot@chromium.org824c3462013-10-10 06:30:18 +0000275 GrGLSLExpr<4> coeff(1);
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000276 if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCoverageOutput) {
bsalomon@google.com018f1792013-04-18 19:36:09 +0000277 // Get (1-A) into coeff
commit-bot@chromium.org824c3462013-10-10 06:30:18 +0000278 coeff = GrGLSLExprCast4(GrGLSLExpr<1>(1) - GrGLSLExprExtractAlpha(inColor));
commit-bot@chromium.org949eef02013-10-01 18:43:29 +0000279 } else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput == header.fCoverageOutput) {
bsalomon@google.com018f1792013-04-18 19:36:09 +0000280 // Get (1-RGBA) into coeff
commit-bot@chromium.org824c3462013-10-10 06:30:18 +0000281 coeff = GrGLSLExpr<4>(1) - inColor;
bsalomon@google.com018f1792013-04-18 19:36:09 +0000282 }
283 // Get coeff * coverage into modulate and then write that to the dual source output.
commit-bot@chromium.org824c3462013-10-10 06:30:18 +0000284 builder->fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inCoverage).c_str());
bsalomon@google.com018f1792013-04-18 19:36:09 +0000285 }
286
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000287 ///////////////////////////////////////////////////////////////////////////
288 // combine color and coverage as frag color
289
bsalomon@google.com5920ac22013-04-19 13:14:45 +0000290 // Get "color * coverage" into fragColor
commit-bot@chromium.org824c3462013-10-10 06:30:18 +0000291 GrGLSLExpr<4> fragColor = inColor * inCoverage;
bsalomon@google.com5920ac22013-04-19 13:14:45 +0000292 // 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 +0000293 if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == header.fCoverageOutput) {
commit-bot@chromium.org824c3462013-10-10 06:30:18 +0000294 GrGLSLExpr<4> dstCoeff = GrGLSLExpr<4>(1) - inCoverage;
295
296 GrGLSLExpr<4> dstContribution = dstCoeff * GrGLSLExpr<4>(builder->dstColor());
297
298 fragColor = fragColor + dstContribution;
bsalomon@google.com5920ac22013-04-19 13:14:45 +0000299 }
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000300 builder->fsCodeAppendf("\t%s = %s;\n", builder->getColorOutputName(), fragColor.c_str());
bsalomon@google.comf2d91552011-05-16 20:56:06 +0000301
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000302 if (!builder->finish(&fProgramID)) {
bsalomon@google.com91961302011-05-09 18:39:58 +0000303 return false;
304 }
305
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000306 fUniformHandles.fRTHeightUni = builder->getRTHeightUniform();
307 fUniformHandles.fDstCopyTopLeftUni = builder->getDstCopyTopLeftUniform();
308 fUniformHandles.fDstCopyScaleUni = builder->getDstCopyScaleUniform();
309 fUniformHandles.fColorUni = builder->getColorUniform();
310 fUniformHandles.fCoverageUni = builder->getCoverageUniform();
311 fUniformHandles.fDstCopySamplerUni = builder->getDstCopySamplerUniform();
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000312 // This must be called after we set fDstCopySamplerUni above.
313 this->initSamplerUniforms();
bsalomon@google.com91961302011-05-09 18:39:58 +0000314
315 return true;
316}
317
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000318void GrGLProgram::initSamplerUniforms() {
bsalomon@google.com9ba4fa62012-07-16 17:36:28 +0000319 GL_CALL(UseProgram(fProgramID));
bsalomon@google.com34cccde2013-01-04 18:34:30 +0000320 GrGLint texUnitIdx = 0;
commit-bot@chromium.org7425c122013-08-14 18:14:19 +0000321 if (fUniformHandles.fDstCopySamplerUni.isValid()) {
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000322 fUniformManager.setSampler(fUniformHandles.fDstCopySamplerUni, texUnitIdx);
bsalomon@google.com804e9942013-06-06 18:04:38 +0000323 fDstCopyTexUnit = texUnitIdx++;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000324 }
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000325 fColorEffects->initSamplers(fUniformManager, &texUnitIdx);
326 fCoverageEffects->initSamplers(fUniformManager, &texUnitIdx);
bsalomon@google.com91961302011-05-09 18:39:58 +0000327}
328
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000329///////////////////////////////////////////////////////////////////////////////
junov@google.comf93e7172011-03-31 21:26:24 +0000330
commit-bot@chromium.org9188a152013-09-05 18:28:24 +0000331void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts,
bsalomon@google.com2c84aa32013-06-06 20:28:57 +0000332 const GrEffectStage* colorStages[],
333 const GrEffectStage* coverageStages[],
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000334 const GrDeviceCoordTexture* dstCopy,
bsalomon@google.com91207482013-02-12 21:45:24 +0000335 SharedGLState* sharedState) {
commit-bot@chromium.org9188a152013-09-05 18:28:24 +0000336 const GrDrawState& drawState = fGpu->getDrawState();
bsalomon@google.com9ba4fa62012-07-16 17:36:28 +0000337
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000338 GrColor color;
339 GrColor coverage;
340 if (blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag) {
341 color = 0;
342 coverage = 0;
343 } else if (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) {
344 color = 0xffffffff;
345 coverage = drawState.getCoverage();
346 } else {
347 color = drawState.getColor();
348 coverage = drawState.getCoverage();
349 }
350
bsalomon@google.com91207482013-02-12 21:45:24 +0000351 this->setColor(drawState, color, sharedState);
352 this->setCoverage(drawState, coverage, sharedState);
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000353 this->setMatrixAndRenderTargetHeight(drawState);
bsalomon@google.com91207482013-02-12 21:45:24 +0000354
355 // Setup the SkXfermode::Mode-based colorfilter uniform if necessary
commit-bot@chromium.org7425c122013-08-14 18:14:19 +0000356 if (fUniformHandles.fColorFilterUni.isValid() &&
bsalomon@google.com91207482013-02-12 21:45:24 +0000357 fColorFilterColor != drawState.getColorFilterColor()) {
358 GrGLfloat c[4];
359 GrColorToRGBAFloat(drawState.getColorFilterColor(), c);
360 fUniformManager.set4fv(fUniformHandles.fColorFilterUni, 0, 1, c);
361 fColorFilterColor = drawState.getColorFilterColor();
362 }
363
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000364 if (NULL != dstCopy) {
commit-bot@chromium.org7425c122013-08-14 18:14:19 +0000365 if (fUniformHandles.fDstCopyTopLeftUni.isValid()) {
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000366 fUniformManager.set2f(fUniformHandles.fDstCopyTopLeftUni,
367 static_cast<GrGLfloat>(dstCopy->offset().fX),
368 static_cast<GrGLfloat>(dstCopy->offset().fY));
369 fUniformManager.set2f(fUniformHandles.fDstCopyScaleUni,
370 1.f / dstCopy->texture()->width(),
371 1.f / dstCopy->texture()->height());
372 GrGLTexture* texture = static_cast<GrGLTexture*>(dstCopy->texture());
373 static GrTextureParams kParams; // the default is clamp, nearest filtering.
commit-bot@chromium.org9188a152013-09-05 18:28:24 +0000374 fGpu->bindTexture(fDstCopyTexUnit, kParams, texture);
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000375 } else {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000376 SkASSERT(!fUniformHandles.fDstCopyScaleUni.isValid());
377 SkASSERT(!fUniformHandles.fDstCopySamplerUni.isValid());
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000378 }
379 } else {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000380 SkASSERT(!fUniformHandles.fDstCopyTopLeftUni.isValid());
381 SkASSERT(!fUniformHandles.fDstCopyScaleUni.isValid());
382 SkASSERT(!fUniformHandles.fDstCopySamplerUni.isValid());
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000383 }
bsalomon@google.comc7818882013-03-20 19:19:53 +0000384
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000385 fColorEffects->setData(fGpu, fUniformManager, colorStages);
386 fCoverageEffects->setData(fGpu, fUniformManager, coverageStages);
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000387
388 if (!fHasVertexShader) {
389 fGpu->disableUnusedTexGen(fNumTexCoordSets);
390 }
skia.committer@gmail.com8ae714b2013-01-05 02:02:05 +0000391}
bsalomon@google.com91207482013-02-12 21:45:24 +0000392
393void GrGLProgram::setColor(const GrDrawState& drawState,
394 GrColor color,
395 SharedGLState* sharedState) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000396 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
jvanverth@google.com054ae992013-04-01 20:06:51 +0000397 if (!drawState.hasColorVertexAttribute()) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000398 switch (header.fColorInput) {
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000399 case GrGLProgramDesc::kAttribute_ColorInput:
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000400 SkASSERT(-1 != header.fColorAttributeIndex);
jvanverth@google.com054ae992013-04-01 20:06:51 +0000401 if (sharedState->fConstAttribColor != color ||
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000402 sharedState->fConstAttribColorIndex != header.fColorAttributeIndex) {
bsalomon@google.com91207482013-02-12 21:45:24 +0000403 // OpenGL ES only supports the float varieties of glVertexAttrib
404 GrGLfloat c[4];
405 GrColorToRGBAFloat(color, c);
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000406 GL_CALL(VertexAttrib4fv(header.fColorAttributeIndex, c));
bsalomon@google.com91207482013-02-12 21:45:24 +0000407 sharedState->fConstAttribColor = color;
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000408 sharedState->fConstAttribColorIndex = header.fColorAttributeIndex;
bsalomon@google.com91207482013-02-12 21:45:24 +0000409 }
410 break;
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000411 case GrGLProgramDesc::kUniform_ColorInput:
bsalomon@google.com91207482013-02-12 21:45:24 +0000412 if (fColor != color) {
413 // OpenGL ES doesn't support unsigned byte varieties of glUniform
414 GrGLfloat c[4];
415 GrColorToRGBAFloat(color, c);
bsalomon@google.com91207482013-02-12 21:45:24 +0000416 fUniformManager.set4fv(fUniformHandles.fColorUni, 0, 1, c);
417 fColor = color;
418 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000419 sharedState->fConstAttribColorIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000420 break;
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000421 case GrGLProgramDesc::kSolidWhite_ColorInput:
422 case GrGLProgramDesc::kTransBlack_ColorInput:
jvanverth@google.com054ae992013-04-01 20:06:51 +0000423 sharedState->fConstAttribColorIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000424 break;
425 default:
426 GrCrash("Unknown color type.");
427 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000428 } else {
429 sharedState->fConstAttribColorIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000430 }
431}
432
433void GrGLProgram::setCoverage(const GrDrawState& drawState,
434 GrColor coverage,
435 SharedGLState* sharedState) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000436 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
jvanverth@google.com054ae992013-04-01 20:06:51 +0000437 if (!drawState.hasCoverageVertexAttribute()) {
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000438 switch (header.fCoverageInput) {
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000439 case GrGLProgramDesc::kAttribute_ColorInput:
jvanverth@google.com054ae992013-04-01 20:06:51 +0000440 if (sharedState->fConstAttribCoverage != coverage ||
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000441 sharedState->fConstAttribCoverageIndex != header.fCoverageAttributeIndex) {
bsalomon@google.com91207482013-02-12 21:45:24 +0000442 // OpenGL ES only supports the float varieties of glVertexAttrib
443 GrGLfloat c[4];
444 GrColorToRGBAFloat(coverage, c);
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000445 GL_CALL(VertexAttrib4fv(header.fCoverageAttributeIndex, c));
bsalomon@google.com91207482013-02-12 21:45:24 +0000446 sharedState->fConstAttribCoverage = coverage;
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000447 sharedState->fConstAttribCoverageIndex = header.fCoverageAttributeIndex;
bsalomon@google.com91207482013-02-12 21:45:24 +0000448 }
449 break;
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000450 case GrGLProgramDesc::kUniform_ColorInput:
bsalomon@google.com91207482013-02-12 21:45:24 +0000451 if (fCoverage != coverage) {
452 // OpenGL ES doesn't support unsigned byte varieties of glUniform
453 GrGLfloat c[4];
454 GrColorToRGBAFloat(coverage, c);
bsalomon@google.com91207482013-02-12 21:45:24 +0000455 fUniformManager.set4fv(fUniformHandles.fCoverageUni, 0, 1, c);
456 fCoverage = coverage;
457 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000458 sharedState->fConstAttribCoverageIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000459 break;
bsalomon@google.com31ec7982013-03-27 18:14:57 +0000460 case GrGLProgramDesc::kSolidWhite_ColorInput:
461 case GrGLProgramDesc::kTransBlack_ColorInput:
jvanverth@google.com054ae992013-04-01 20:06:51 +0000462 sharedState->fConstAttribCoverageIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000463 break;
464 default:
465 GrCrash("Unknown coverage type.");
466 }
jvanverth@google.com054ae992013-04-01 20:06:51 +0000467 } else {
468 sharedState->fConstAttribCoverageIndex = -1;
bsalomon@google.com91207482013-02-12 21:45:24 +0000469 }
470}
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000471
472void GrGLProgram::setMatrixAndRenderTargetHeight(const GrDrawState& drawState) {
473 const GrRenderTarget* rt = drawState.getRenderTarget();
474 SkISize size;
475 size.set(rt->width(), rt->height());
476
477 // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
commit-bot@chromium.org7425c122013-08-14 18:14:19 +0000478 if (fUniformHandles.fRTHeightUni.isValid() &&
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000479 fMatrixState.fRenderTargetSize.fHeight != size.fHeight) {
480 fUniformManager.set1f(fUniformHandles.fRTHeightUni, SkIntToScalar(size.fHeight));
481 }
482
commit-bot@chromium.org6b30e452013-10-04 20:02:53 +0000483 if (!fHasVertexShader) {
484 SkASSERT(!fUniformHandles.fViewMatrixUni.isValid());
485 fGpu->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin());
486 } else if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
487 fMatrixState.fRenderTargetSize != size ||
488 !fMatrixState.fViewMatrix.cheapEqualTo(drawState.getViewMatrix())) {
489 SkASSERT(fUniformHandles.fViewMatrixUni.isValid());
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000490
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000491 fMatrixState.fViewMatrix = drawState.getViewMatrix();
492 fMatrixState.fRenderTargetSize = size;
493 fMatrixState.fRenderTargetOrigin = rt->origin();
commit-bot@chromium.org215a6822013-09-05 18:28:42 +0000494
495 GrGLfloat viewMatrix[3 * 3];
496 fMatrixState.getGLMatrix<3>(viewMatrix);
497 fUniformManager.setMatrix3f(fUniformHandles.fViewMatrixUni, viewMatrix);
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000498 }
499}