blob: 5dd09f018abf93ebf0bec84517625456886883ce [file] [log] [blame]
junov@google.comf93e7172011-03-31 21:26:24 +00001/*
2 Copyright 2011 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17#include "GrGLProgram.h"
18
19#include "GrBinHashKey.h"
20#include "GrGLConfig.h"
21#include "GrGLEffect.h"
22#include "GrMemory.h"
23#include "GrStringBuilder.h"
24
25namespace {
26
27const char* GrPrecision() {
28 if (GR_GL_SUPPORT_ES2) {
29 return "mediump";
30 } else {
31 return "";
32 }
33}
34
35const char* GrShaderPrecision() {
36 if (GR_GL_SUPPORT_ES2) {
37 return "precision mediump float;\n";
38 } else {
39 return "";
40 }
41}
42
43} // namespace
44
45#if ATTRIBUTE_MATRIX
46 #define VIEW_MATRIX_NAME "aViewM"
47#else
48 #define VIEW_MATRIX_NAME "uViewM"
49#endif
50
51#define POS_ATTR_NAME "aPosition"
52#define COL_ATTR_NAME "aColor"
53
54// for variable names etc
55typedef GrSStringBuilder<16> GrTokenString;
56
57static inline void tex_attr_name(int coordIdx, GrStringBuilder* s) {
58 *s = "aTexCoord";
59 s->appendInt(coordIdx);
60}
61
62static inline const char* float_vector_type(int count) {
63 static const char* FLOAT_VECS[] = {"ERROR", "float", "vec2", "vec3", "vec4"};
64 GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(FLOAT_VECS));
65 return FLOAT_VECS[count];
66}
67
68static inline const char* vector_homog_coord(int count) {
69 static const char* HOMOGS[] = {"ERROR", "", ".y", ".z", ".w"};
70 GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(HOMOGS));
71 return HOMOGS[count];
72}
73
74static inline const char* vector_nonhomog_coords(int count) {
75 static const char* NONHOMOGS[] = {"ERROR", "", ".x", ".xy", ".xyz"};
76 GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(NONHOMOGS));
77 return NONHOMOGS[count];
78}
79
80static inline const char* vector_all_coords(int count) {
81 static const char* ALL[] = {"ERROR", "", ".xy", ".xyz", ".xyzw"};
82 GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(ALL));
83 return ALL[count];
84}
85
86static void tex_matrix_name(int stage, GrStringBuilder* s) {
87#if ATTRIBUTE_MATRIX
88 *s = "aTexM";
89#else
90 *s = "uTexM";
91#endif
92 s->appendInt(stage);
93}
94
95static void sampler_name(int stage, GrStringBuilder* s) {
96 *s = "uSampler";
97 s->appendInt(stage);
98}
99
100static void stage_varying_name(int stage, GrStringBuilder* s) {
101 *s = "vStage";
102 s->appendInt(stage);
103}
104
105static void radial2_param_name(int stage, GrStringBuilder* s) {
106 *s = "uRadial2Params";
107 s->appendInt(stage);
108}
109
110static void radial2_varying_name(int stage, GrStringBuilder* s) {
111 *s = "vB";
112 s->appendInt(stage);
113}
114
115GrGLProgram::GrGLProgram() {
116 for(int stage = 0; stage < GrDrawTarget::kNumStages; ++stage) {
117 fStageEffects[stage] = NULL;
118 }
119}
120
121GrGLProgram::~GrGLProgram() {
122
123}
124
125void GrGLProgram::buildKey(GrBinHashKeyBuilder& key) const {
126 // Add stage configuration to the key
127 key.keyData(reinterpret_cast<const uint8_t*>(&fProgramDesc), sizeof(ProgramDesc));
128
129 for(int stage = 0; stage < GrDrawTarget::kNumStages; ++stage) {
130 // First pass: count effects and write the count to the key.
131 // This may seem like we are adding redundant data to the
132 // key, but in ensures the one key cannot be a prefix of
133 // another key, or identical to the key of a different program.
134 GrGLEffect* currentEffect = fStageEffects[stage];
135 uint8_t effectCount = 0;
136 while (currentEffect) {
137 GrAssert(effectCount < 255); // overflow detection
138 ++effectCount;
139 currentEffect = currentEffect->nextEffect();
140 }
141 key.keyData(reinterpret_cast<const uint8_t*>(&effectCount), sizeof(uint8_t));
142
143 // Second pass: continue building key using the effects
144 currentEffect = fStageEffects[stage];
145 while (currentEffect) {
146 fStageEffects[stage]->buildKey(key);
147 }
148 }
149}
150
151bool GrGLProgram::doGLSetup(GrPrimitiveType type,
152 GrGLProgram::CachedData* programData) const {
153 for (int stage = 0; stage < GrDrawTarget::kNumStages; ++stage) {
154 GrGLEffect* effect = fStageEffects[stage];
155 if (effect) {
156 if (!effect->doGLSetup(type, programData->fProgramID)) {
157 return false;
158 }
159 }
160 }
161
162 return true;
163}
164
165void GrGLProgram::doGLPost() const {
166 for (int stage = 0; stage < GrDrawTarget::kNumStages; ++stage) {
167 GrGLEffect* effect = fStageEffects[stage];
168 if (effect) {
169 effect->doGLPost();
170 }
171 }
172}
173
174void GrGLProgram::genProgram(GrGLProgram::CachedData* programData,
175 const GrDrawTarget* target) const {
176
177 ShaderCodeSegments segments;
178 const uint32_t& layout = fProgramDesc.fVertexLayout;
179
180 memset(&programData->fUniLocations, 0, sizeof(UniLocations));
181
182 bool haveColor = !(ProgramDesc::kVertexColorAllOnes_OptFlagBit &
183 fProgramDesc.fOptFlags);
184
185#if ATTRIBUTE_MATRIX
186 segments.fVSAttrs = "attribute mat3 " VIEW_MATRIX_NAME ";\n";
187#else
188 segments.fVSUnis = "uniform mat3 " VIEW_MATRIX_NAME ";\n";
189 segments.fVSAttrs = "";
190#endif
191 segments.fVSAttrs += "attribute vec2 " POS_ATTR_NAME ";\n";
192 if (haveColor) {
193 segments.fVSAttrs += "attribute vec4 " COL_ATTR_NAME ";\n";
194 segments.fVaryings = "varying vec4 vColor;\n";
195 } else {
196 segments.fVaryings = "";
197 }
198
199 segments.fVSCode = "void main() {\n"
200 "\tvec3 pos3 = " VIEW_MATRIX_NAME " * vec3(" POS_ATTR_NAME ", 1);\n"
201 "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n";
202 if (haveColor) {
203 segments.fVSCode += "\tvColor = " COL_ATTR_NAME ";\n";
204 }
205
206 if (!(fProgramDesc.fOptFlags & ProgramDesc::kNotPoints_OptFlagBit)) {
207 segments.fVSCode += "\tgl_PointSize = 1.0;\n";
208 }
209 segments.fFSCode = "void main() {\n";
210
211 // add texture coordinates that are used to the list of vertex attr decls
212 GrTokenString texCoordAttrs[GrDrawTarget::kMaxTexCoords];
213 for (int t = 0; t < GrDrawTarget::kMaxTexCoords; ++t) {
214 if (target->VertexUsesTexCoordIdx(t, layout)) {
215 tex_attr_name(t, texCoordAttrs + t);
216
217 segments.fVSAttrs += "attribute vec2 ";
218 segments.fVSAttrs += texCoordAttrs[t];
219 segments.fVSAttrs += ";\n";
220 }
221 }
222
223 // for each enabled stage figure out what the input coordinates are
224 // and count the number of stages in use.
225 const char* stageInCoords[GrDrawTarget::kNumStages];
226 int numActiveStages = 0;
227
228 for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
229 if (fProgramDesc.fStages[s].fEnabled) {
230 if (GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s) & layout) {
231 stageInCoords[s] = POS_ATTR_NAME;
232 } else {
233 int tcIdx = GrDrawTarget::VertexTexCoordsForStage(s, layout);
234 // we better have input tex coordinates if stage is enabled.
235 GrAssert(tcIdx >= 0);
236 GrAssert(texCoordAttrs[tcIdx].length());
237 stageInCoords[s] = texCoordAttrs[tcIdx].cstr();
238 }
239 ++numActiveStages;
240 }
241 }
242
243 GrTokenString inColor = "vColor";
244
245 // if we have active stages string them together, feeding the output color
246 // of each to the next and generating code for each stage.
247 if (numActiveStages) {
248 int currActiveStage = 0;
249 for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
250 if (fProgramDesc.fStages[s].fEnabled) {
251 GrTokenString outColor;
252 if (currActiveStage < (numActiveStages - 1)) {
253 outColor = "color";
254 outColor.appendInt(currActiveStage);
255 segments.fFSCode += "\tvec4 ";
256 segments.fFSCode += outColor;
257 segments.fFSCode += ";\n";
258 } else {
259 outColor = "gl_FragColor";
260 }
261
262 genStageCode(s,
263 fProgramDesc.fStages[s],
264 haveColor ? inColor.cstr() : NULL,
265 outColor.cstr(),
266 stageInCoords[s],
267 &segments,
268 &programData->fUniLocations.fStages[s]);
269 ++currActiveStage;
270 inColor = outColor;
271 haveColor = true;
272 }
273 }
274 } else {
275 segments.fFSCode += "\tgl_FragColor = ";
276 if (haveColor) {
277 segments.fFSCode += inColor;
278 } else {
279 segments.fFSCode += "vec4(1,1,1,1)";
280 }
281 segments.fFSCode += ";\n";
282 }
283 segments.fFSCode += "}\n";
284 segments.fVSCode += "}\n";
285
286
287 const char* strings[4];
288 int lengths[4];
289 int stringCnt = 0;
290
291 if (segments.fVSUnis.length()) {
292 strings[stringCnt] = segments.fVSUnis.cstr();
293 lengths[stringCnt] = segments.fVSUnis.length();
294 ++stringCnt;
295 }
296 if (segments.fVSAttrs.length()) {
297 strings[stringCnt] = segments.fVSAttrs.cstr();
298 lengths[stringCnt] = segments.fVSAttrs.length();
299 ++stringCnt;
300 }
301 if (segments.fVaryings.length()) {
302 strings[stringCnt] = segments.fVaryings.cstr();
303 lengths[stringCnt] = segments.fVaryings.length();
304 ++stringCnt;
305 }
306
307 GrAssert(segments.fVSCode.length());
308 strings[stringCnt] = segments.fVSCode.cstr();
309 lengths[stringCnt] = segments.fVSCode.length();
310 ++stringCnt;
311
312#if PRINT_SHADERS
313 GrPrintf("%s%s%s%s\n",
314 segments.fVSUnis.cstr(),
315 segments.fVSAttrs.cstr(),
316 segments.fVaryings.cstr(),
317 segments.fVSCode.cstr());
318#endif
319 programData->fVShaderID = CompileShader(GR_GL_VERTEX_SHADER,
320 stringCnt,
321 strings,
322 lengths);
323
324 stringCnt = 0;
325
326 if (strlen(GrShaderPrecision()) > 1) {
327 strings[stringCnt] = GrShaderPrecision();
328 lengths[stringCnt] = strlen(GrShaderPrecision());
329 ++stringCnt;
330 }
331 if (segments.fFSUnis.length()) {
332 strings[stringCnt] = segments.fFSUnis.cstr();
333 lengths[stringCnt] = segments.fFSUnis.length();
334 ++stringCnt;
335 }
336 if (segments.fVaryings.length()) {
337 strings[stringCnt] = segments.fVaryings.cstr();
338 lengths[stringCnt] = segments.fVaryings.length();
339 ++stringCnt;
340 }
341
342 GrAssert(segments.fFSCode.length());
343 strings[stringCnt] = segments.fFSCode.cstr();
344 lengths[stringCnt] = segments.fFSCode.length();
345 ++stringCnt;
346
347#if PRINT_SHADERS
348 GrPrintf("%s%s%s%s\n",
349 GR_SHADER_PRECISION,
350 segments.fFSUnis.cstr(),
351 segments.fVaryings.cstr(),
352 segments.fFSCode.cstr());
353#endif
354 programData->fFShaderID = CompileShader(GR_GL_FRAGMENT_SHADER,
355 stringCnt,
356 strings,
357 lengths);
358
359 programData->fProgramID = GR_GL(CreateProgram());
360 const GrGLint& progID = programData->fProgramID;
361
362 GR_GL(AttachShader(progID, programData->fVShaderID));
363 GR_GL(AttachShader(progID, programData->fFShaderID));
364
365 // Bind the attrib locations to same values for all shaders
366 GR_GL(BindAttribLocation(progID, POS_ATTR_LOCATION, POS_ATTR_NAME));
367 for (int t = 0; t < GrDrawTarget::kMaxTexCoords; ++t) {
368 if (texCoordAttrs[t].length()) {
369 GR_GL(BindAttribLocation(progID,
370 TEX_ATTR_LOCATION(t),
371 texCoordAttrs[t].cstr()));
372 }
373 }
374
375#if ATTRIBUTE_MATRIX
376 // set unis to a bogus value so that checks against -1 before
377 // flushing will pass.
378 GR_GL(BindAttribLocation(progID,
379 VIEWMAT_ATTR_LOCATION,
380 VIEW_MATRIX_NAME));
381
382 program->fUniLocations.fViewMatrixUni = BOGUS_MATRIX_UNI_LOCATION;
383
384 for (int s = 0; s < kNumStages; ++s) {
385 if (fProgramDesc.fStages[s].fEnabled) {
386 GrStringBuilder matName;
387 tex_matrix_name(s, &matName);
388 GR_GL(BindAttribLocation(progID,
389 TEXMAT_ATTR_LOCATION(s),
390 matName.cstr()));
391 program->fUniLocations.fStages[s].fTextureMatrixUni =
392 BOGUS_MATRIX_UNI_LOCATION;
393 }
394 }
395#endif
396
397 GR_GL(BindAttribLocation(progID, COL_ATTR_LOCATION, COL_ATTR_NAME));
398
399 GR_GL(LinkProgram(progID));
400
401 GrGLint linked = GR_GL_INIT_ZERO;
402 GR_GL(GetProgramiv(progID, GR_GL_LINK_STATUS, &linked));
403 if (!linked) {
404 GrGLint infoLen = GR_GL_INIT_ZERO;
405 GR_GL(GetProgramiv(progID, GR_GL_INFO_LOG_LENGTH, &infoLen));
406 GrAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
407 if (infoLen > 0) {
408 GR_GL(GetProgramInfoLog(progID,
409 infoLen+1,
410 NULL,
411 (char*)log.get()));
412 GrPrintf((char*)log.get());
413 }
414 GrAssert(!"Error linking program");
415 GR_GL(DeleteProgram(progID));
416 programData->fProgramID = 0;
417 return;
418 }
419
420 // Get uniform locations
421#if !ATTRIBUTE_MATRIX
422 programData->fUniLocations.fViewMatrixUni =
423 GR_GL(GetUniformLocation(progID, VIEW_MATRIX_NAME));
424 GrAssert(-1 != programData->fUniLocations.fViewMatrixUni);
425#endif
426 for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
427 StageUniLocations& locations = programData->fUniLocations.fStages[s];
428 if (fProgramDesc.fStages[s].fEnabled) {
429#if !ATTRIBUTE_MATRIX
430 if (locations.fTextureMatrixUni) {
431 GrTokenString texMName;
432 tex_matrix_name(s, &texMName);
433 locations.fTextureMatrixUni = GR_GL(GetUniformLocation(
434 progID,
435 texMName.cstr()));
436 GrAssert(-1 != locations.fTextureMatrixUni);
437 } else {
438 locations.fTextureMatrixUni = -1;
439
440 }
441#endif
442
443 if (locations.fSamplerUni) {
444 GrTokenString samplerName;
445 sampler_name(s, &samplerName);
446 locations.fSamplerUni = GR_GL(GetUniformLocation(
447 progID,
448 samplerName.cstr()));
449 GrAssert(-1 != locations.fSamplerUni);
450 } else {
451 locations.fSamplerUni = -1;
452 }
453
454 if (locations.fRadial2Uni) {
455 GrTokenString radial2ParamName;
456 radial2_param_name(s, &radial2ParamName);
457 locations.fRadial2Uni = GR_GL(GetUniformLocation(
458 progID,
459 radial2ParamName.cstr()));
460 GrAssert(-1 != locations.fRadial2Uni);
461 } else {
462 locations.fRadial2Uni = -1;
463 }
464 } else {
465 locations.fSamplerUni = -1;
466 locations.fRadial2Uni = -1;
467 locations.fTextureMatrixUni = -1;
468 }
469 }
470 GR_GL(UseProgram(progID));
471
472 // init sampler unis and set bogus values for state tracking
473 for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
474 if (-1 != programData->fUniLocations.fStages[s].fSamplerUni) {
475 GR_GL(Uniform1i(programData->fUniLocations.fStages[s].fSamplerUni, s));
476 }
477 programData->fTextureMatrices[s] = GrMatrix::InvalidMatrix();
478 programData->fRadial2CenterX1[s] = GR_ScalarMax;
479 programData->fRadial2Radius0[s] = -GR_ScalarMax;
480 }
481 programData->fViewMatrix = GrMatrix::InvalidMatrix();
482}
483
484GrGLuint GrGLProgram::CompileShader(GrGLenum type,
485 int stringCnt,
486 const char** strings,
487 int* stringLengths) {
488 GrGLuint shader = GR_GL(CreateShader(type));
489 if (0 == shader) {
490 return 0;
491 }
492
493 GrGLint compiled = GR_GL_INIT_ZERO;
494 GR_GL(ShaderSource(shader, stringCnt, strings, stringLengths));
495 GR_GL(CompileShader(shader));
496 GR_GL(GetShaderiv(shader, GR_GL_COMPILE_STATUS, &compiled));
497
498 if (!compiled) {
499 GrGLint infoLen = GR_GL_INIT_ZERO;
500 GR_GL(GetShaderiv(shader, GR_GL_INFO_LOG_LENGTH, &infoLen));
501 GrAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
502 if (infoLen > 0) {
503 GR_GL(GetShaderInfoLog(shader, infoLen+1, NULL, (char*)log.get()));
504 for (int i = 0; i < stringCnt; ++i) {
505 if (NULL == stringLengths || stringLengths[i] < 0) {
506 GrPrintf(strings[i]);
507 } else {
508 GrPrintf("%.*s", stringLengths[i], strings[i]);
509 }
510 }
511 GrPrintf("\n%s", log.get());
512 }
513 GrAssert(!"Shader compilation failed!");
514 GR_GL(DeleteShader(shader));
515 return 0;
516 }
517 return shader;
518}
519
520//============================================================================
521// Stage code generation
522//============================================================================
523
524void GrGLProgram::genStageCode(int stageNum,
525 const GrGLProgram::ProgramDesc::StageDesc& desc,
526 const char* fsInColor, // NULL means no incoming color
527 const char* fsOutColor,
528 const char* vsInCoord,
529 ShaderCodeSegments* segments,
530 StageUniLocations* locations) const {
531
532 GrAssert(stageNum >= 0 && stageNum <= 9);
533
534 GrTokenString varyingName;
535 stage_varying_name(stageNum, &varyingName);
536
537 // First decide how many coords are needed to access the texture
538 // Right now it's always 2 but we could start using 1D textures for
539 // gradients.
540 static const int coordDims = 2;
541 int varyingDims;
542 /// Vertex Shader Stuff
543
544 // decide whether we need a matrix to transform texture coords
545 // and whether the varying needs a perspective coord.
546 GrTokenString texMName;
547 tex_matrix_name(stageNum, &texMName);
548 if (desc.fOptFlags & ProgramDesc::StageDesc::kIdentityMatrix_OptFlagBit) {
549 varyingDims = coordDims;
550 } else {
551 #if ATTRIBUTE_MATRIX
552 segments->fVSAttrs += "attribute mat3 ";
553 segments->fVSAttrs += texMName;
554 segments->fVSAttrs += ";\n";
555 #else
556 segments->fVSUnis += "uniform mat3 ";
557 segments->fVSUnis += texMName;
558 segments->fVSUnis += ";\n";
559 locations->fTextureMatrixUni = 1;
560 #endif
561 if (desc.fOptFlags & ProgramDesc::StageDesc::kNoPerspective_OptFlagBit) {
562 varyingDims = coordDims;
563 } else {
564 varyingDims = coordDims + 1;
565 }
566 }
567
568 GrTokenString samplerName;
569 sampler_name(stageNum, &samplerName);
570 segments->fFSUnis += "uniform sampler2D ";
571 segments->fFSUnis += samplerName;
572 segments->fFSUnis += ";\n";
573 locations->fSamplerUni = 1;
574
575 segments->fVaryings += "varying ";
576 segments->fVaryings += float_vector_type(varyingDims);
577 segments->fVaryings += " ";
578 segments->fVaryings += varyingName;
579 segments->fVaryings += ";\n";
580
581 if (desc.fOptFlags & ProgramDesc::StageDesc::kIdentityMatrix_OptFlagBit) {
582 GrAssert(varyingDims == coordDims);
583 segments->fVSCode += "\t";
584 segments->fVSCode += varyingName;
585 segments->fVSCode += " = ";
586 segments->fVSCode += vsInCoord;
587 segments->fVSCode += ";\n";
588 } else {
589 segments->fVSCode += "\t";
590 segments->fVSCode += varyingName;
591 segments->fVSCode += " = (";
592 segments->fVSCode += texMName;
593 segments->fVSCode += " * vec3(";
594 segments->fVSCode += vsInCoord;
595 segments->fVSCode += ", 1))";
596 segments->fVSCode += vector_all_coords(varyingDims);
597 segments->fVSCode += ";\n";
598 }
599
600 GrTokenString radial2ParamsName;
601 radial2_param_name(stageNum, &radial2ParamsName);
602 // for radial grads without perspective we can pass the linear
603 // part of the quadratic as a varying.
604 GrTokenString radial2VaryingName;
605 radial2_varying_name(stageNum, &radial2VaryingName);
606
607 if (ProgramDesc::StageDesc::kRadial2Gradient_CoordMapping == desc.fCoordMapping) {
608
609 segments->fVSUnis += "uniform ";
610 segments->fVSUnis += GrPrecision();
611 segments->fVSUnis += " float ";
612 segments->fVSUnis += radial2ParamsName;
613 segments->fVSUnis += "[6];\n";
614
615 segments->fFSUnis += "uniform ";
616 segments->fFSUnis += GrPrecision();
617 segments->fFSUnis += " float ";
618 segments->fFSUnis += radial2ParamsName;
619 segments->fFSUnis += "[6];\n";
620 locations->fRadial2Uni = 1;
621
622 // if there is perspective we don't interpolate this
623 if (varyingDims == coordDims) {
624 GrAssert(2 == coordDims);
625 segments->fVaryings += "varying float ";
626 segments->fVaryings += radial2VaryingName;
627 segments->fVaryings += ";\n";
628
629 segments->fVSCode += "\t";
630 segments->fVSCode += radial2VaryingName;
631 segments->fVSCode += " = 2.0 * (";
632 segments->fVSCode += radial2ParamsName;
633 segments->fVSCode += "[2] * ";
634 segments->fVSCode += varyingName;
635 segments->fVSCode += ".x ";
636 segments->fVSCode += " - ";
637 segments->fVSCode += radial2ParamsName;
638 segments->fVSCode += "[3]);\n";
639 }
640 }
641
642 /// Fragment Shader Stuff
643 GrTokenString fsCoordName;
644 // function used to access the shader, may be made projective
645 GrTokenString texFunc("texture2D");
646 if (desc.fOptFlags & (ProgramDesc::StageDesc::kIdentityMatrix_OptFlagBit |
647 ProgramDesc::StageDesc::kNoPerspective_OptFlagBit)) {
648 GrAssert(varyingDims == coordDims);
649 fsCoordName = varyingName;
650 } else {
651 // if we have to do some non-matrix op on the varyings to get
652 // our final tex coords then when in perspective we have to
653 // do an explicit divide
654 if (ProgramDesc::StageDesc::kIdentity_CoordMapping == desc.fCoordMapping) {
655 texFunc += "Proj";
656 fsCoordName = varyingName;
657 } else {
658 fsCoordName = "tCoord";
659 fsCoordName.appendInt(stageNum);
660
661 segments->fFSCode += "\t";
662 segments->fFSCode += float_vector_type(coordDims);
663 segments->fFSCode += " ";
664 segments->fFSCode += fsCoordName;
665 segments->fFSCode += " = ";
666 segments->fFSCode += varyingName;
667 segments->fFSCode += vector_nonhomog_coords(varyingDims);
668 segments->fFSCode += " / ";
669 segments->fFSCode += varyingName;
670 segments->fFSCode += vector_homog_coord(varyingDims);
671 segments->fFSCode += ";\n";
672 }
673 }
674
675 GrSStringBuilder<96> sampleCoords;
676 switch (desc.fCoordMapping) {
677 case ProgramDesc::StageDesc::kIdentity_CoordMapping:
678 sampleCoords = fsCoordName;
679 break;
680 case ProgramDesc::StageDesc::kSweepGradient_CoordMapping:
681 sampleCoords = "vec2(atan(-";
682 sampleCoords += fsCoordName;
683 sampleCoords += ".y, -";
684 sampleCoords += fsCoordName;
685 sampleCoords += ".x)*0.1591549430918 + 0.5, 0.5)";
686 break;
687 case ProgramDesc::StageDesc::kRadialGradient_CoordMapping:
688 sampleCoords = "vec2(length(";
689 sampleCoords += fsCoordName;
690 sampleCoords += ".xy), 0.5)";
691 break;
692 case ProgramDesc::StageDesc::kRadial2Gradient_CoordMapping: {
693 GrTokenString cName = "c";
694 GrTokenString ac4Name = "ac4";
695 GrTokenString rootName = "root";
696
697 cName.appendInt(stageNum);
698 ac4Name.appendInt(stageNum);
699 rootName.appendInt(stageNum);
700
701 GrTokenString bVar;
702 if (coordDims == varyingDims) {
703 bVar = radial2VaryingName;
704 GrAssert(2 == varyingDims);
705 } else {
706 GrAssert(3 == varyingDims);
707 bVar = "b";
708 bVar.appendInt(stageNum);
709 segments->fFSCode += "\tfloat ";
710 segments->fFSCode += bVar;
711 segments->fFSCode += " = 2.0 * (";
712 segments->fFSCode += radial2ParamsName;
713 segments->fFSCode += "[2] * ";
714 segments->fFSCode += fsCoordName;
715 segments->fFSCode += ".x ";
716 segments->fFSCode += " - ";
717 segments->fFSCode += radial2ParamsName;
718 segments->fFSCode += "[3]);\n";
719 }
720
721 segments->fFSCode += "\tfloat ";
722 segments->fFSCode += cName;
723 segments->fFSCode += " = dot(";
724 segments->fFSCode += fsCoordName;
725 segments->fFSCode += ", ";
726 segments->fFSCode += fsCoordName;
727 segments->fFSCode += ") + ";
728 segments->fFSCode += " - ";
729 segments->fFSCode += radial2ParamsName;
730 segments->fFSCode += "[4];\n";
731
732 segments->fFSCode += "\tfloat ";
733 segments->fFSCode += ac4Name;
734 segments->fFSCode += " = ";
735 segments->fFSCode += radial2ParamsName;
736 segments->fFSCode += "[0] * 4.0 * ";
737 segments->fFSCode += cName;
738 segments->fFSCode += ";\n";
739
740 segments->fFSCode += "\tfloat ";
741 segments->fFSCode += rootName;
742 segments->fFSCode += " = sqrt(abs(";
743 segments->fFSCode += bVar;
744 segments->fFSCode += " * ";
745 segments->fFSCode += bVar;
746 segments->fFSCode += " - ";
747 segments->fFSCode += ac4Name;
748 segments->fFSCode += "));\n";
749
750 sampleCoords = "vec2((-";
751 sampleCoords += bVar;
752 sampleCoords += " + ";
753 sampleCoords += radial2ParamsName;
754 sampleCoords += "[5] * ";
755 sampleCoords += rootName;
756 sampleCoords += ") * ";
757 sampleCoords += radial2ParamsName;
758 sampleCoords += "[1], 0.5)\n";
759 break;}
760 };
761
762 segments->fFSCode += "\t";
763 segments->fFSCode += fsOutColor;
764 segments->fFSCode += " = ";
765 if (NULL != fsInColor) {
766 segments->fFSCode += fsInColor;
767 segments->fFSCode += " * ";
768 }
769 segments->fFSCode += texFunc;
770 segments->fFSCode += "(";
771 segments->fFSCode += samplerName;
772 segments->fFSCode += ", ";
773 segments->fFSCode += sampleCoords;
774 segments->fFSCode += ")";
775 if (desc.fModulation == ProgramDesc::StageDesc::kAlpha_Modulation) {
776 segments->fFSCode += ".aaaa";
777 }
778 segments->fFSCode += ";\n";
779
780 if(fStageEffects[stageNum]) {
781 fStageEffects[stageNum]->genShaderCode(segments);
782 }
783}
784