blob: 6abfcdc75824586e6cf17cdd6154e8862e1cd7dd [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
twiz@google.com0f31ca72011-03-18 17:38:11 +00002 Copyright 2011 Google Inc.
reed@google.comac10a2d2010-12-22 21:39:39 +00003
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
18#include "GrGLConfig.h"
19
reed@google.comac10a2d2010-12-22 21:39:39 +000020#include "GrGpuGLShaders2.h"
21#include "GrGpuVertex.h"
22#include "GrMemory.h"
23#include "GrStringBuilder.h"
24
reed@google.comac10a2d2010-12-22 21:39:39 +000025#define PRINT_SHADERS 0
26
bsalomon@google.com4be283f2011-04-19 21:15:09 +000027#define SKIP_CACHE_CHECK true
reed@google.comac10a2d2010-12-22 21:39:39 +000028
reed@google.comac10a2d2010-12-22 21:39:39 +000029#define POS_ATTR_LOCATION 0
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000030#define TEX_ATTR_LOCATION(X) (1 + X)
31#define COL_ATTR_LOCATION (2 + GrDrawTarget::kMaxTexCoords)
bsalomon@google.com4be283f2011-04-19 21:15:09 +000032#if GR_GL_ATTRIBUTE_MATRICES
33 #define VIEWMAT_ATTR_LOCATION (3 + GrDrawTarget::kMaxTexCoords)
34 #define TEXMAT_ATTR_LOCATION(X) (6 + GrDrawTarget::kMaxTexCoords + 3 * (X))
35 #define BOGUS_MATRIX_UNI_LOCATION 1000
reed@google.comac10a2d2010-12-22 21:39:39 +000036#endif
37
reed@google.comd2938db2011-01-28 20:54:15 +000038#define GR_UINT32_MAX static_cast<uint32_t>(-1)
39
twiz@google.comb65e0cb2011-03-18 20:41:44 +000040namespace {
41
42const char* GrPrecision() {
43 if (GR_GL_SUPPORT_ES2) {
44 return "mediump";
45 } else {
46 return "";
47 }
48}
49
50const char* GrShaderPrecision() {
51 if (GR_GL_SUPPORT_ES2) {
52 return "precision mediump float;\n";
53 } else {
54 return "";
55 }
56}
57
58} // namespace
59
reed@google.comac10a2d2010-12-22 21:39:39 +000060struct GrGpuGLShaders2::StageUniLocations {
twiz@google.com0f31ca72011-03-18 17:38:11 +000061 GrGLint fTextureMatrixUni;
62 GrGLint fSamplerUni;
63 GrGLint fRadial2Uni;
reed@google.comac10a2d2010-12-22 21:39:39 +000064};
65
66struct GrGpuGLShaders2::UniLocations {
twiz@google.com0f31ca72011-03-18 17:38:11 +000067 GrGLint fViewMatrixUni;
bsalomon@google.com4be283f2011-04-19 21:15:09 +000068 GrGLint fColorUni;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000069 StageUniLocations fStages[kNumStages];
reed@google.comac10a2d2010-12-22 21:39:39 +000070};
71
72// Records per-program information
73// we can specify the attribute locations so that they are constant
74// across our shaders. But the driver determines the uniform locations
75// at link time. We don't need to remember the sampler uniform location
76// because we will bind a texture slot to it and never change it
77// Uniforms are program-local so we can't rely on fHWState to hold the
78// previous uniform state after a program change.
79struct GrGpuGLShaders2::Program {
80 // IDs
twiz@google.com0f31ca72011-03-18 17:38:11 +000081 GrGLuint fVShaderID;
82 GrGLuint fFShaderID;
83 GrGLuint fProgramID;
reed@google.comac10a2d2010-12-22 21:39:39 +000084
85 // shader uniform locations (-1 if shader doesn't use them)
86 UniLocations fUniLocations;
87
88 // these reflect the current values of uniforms
89 // (GL uniform values travel with program)
90 GrMatrix fViewMatrix;
bsalomon@google.com4be283f2011-04-19 21:15:09 +000091 GrColor fColor;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000092 GrMatrix fTextureMatrices[kNumStages];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000093 GrScalar fRadial2CenterX1[kNumStages];
94 GrScalar fRadial2Radius0[kNumStages];
95 bool fRadial2PosRoot[kNumStages];
reed@google.comac10a2d2010-12-22 21:39:39 +000096
97};
98
99// must be tightly packed
100struct GrGpuGLShaders2::StageDesc {
101 enum OptFlagBits {
102 kNoPerspective_OptFlagBit = 0x1,
103 kIdentityMatrix_OptFlagBit = 0x2,
104 };
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000105 unsigned fOptFlags : 8;
106
107 unsigned fEnabled : 8;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000108
reed@google.comac10a2d2010-12-22 21:39:39 +0000109 enum Modulation {
110 kColor_Modulation,
111 kAlpha_Modulation,
112 } fModulation : 8;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000113
reed@google.comac10a2d2010-12-22 21:39:39 +0000114 enum CoordMapping {
115 kIdentity_CoordMapping,
116 kRadialGradient_CoordMapping,
117 kSweepGradient_CoordMapping,
118 kRadial2Gradient_CoordMapping,
119 } fCoordMapping : 8;
120};
121
122// must be tightly packed
123struct GrGpuGLShaders2::ProgramDesc {
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000124 ProgramDesc() {
125 // since we use this as a key we can't have any unitialized padding
126 memset(this, 0, sizeof(ProgramDesc));
127 }
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000128
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000129 GrVertexLayout fVertexLayout; // stripped of bits that don't affect
130 // program generation.
reed@google.comac10a2d2010-12-22 21:39:39 +0000131 enum {
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000132 kNone_ColorType = 0,
133 kAttribute_ColorType = 1,
134 kUniform_ColorType = 2,
135 } fColorType;
136 bool fEmitsPointSize;
reed@google.comac10a2d2010-12-22 21:39:39 +0000137
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000138 StageDesc fStages[kNumStages];
reed@google.comac10a2d2010-12-22 21:39:39 +0000139
140 bool operator == (const ProgramDesc& desc) const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000141 return 0 == memcmp(this, &desc, sizeof(ProgramDesc));
142 }
143};
144
145#include "GrTHashCache.h"
146
147class GrGpuGLShaders2::ProgramCache : public ::GrNoncopyable {
148private:
149 struct Entry;
150 class HashKey {
151 public:
152 HashKey();
153 HashKey(const ProgramDesc& desc);
154 static const HashKey& GetKey(const Entry&);
155 static bool EQ(const Entry&, const HashKey&);
156 static bool LT(const Entry&, const HashKey&);
157 bool operator <(const HashKey& key) const;
158 bool operator ==(const HashKey& key) const;
159 uint32_t getHash() const;
160 private:
161 ProgramDesc fDesc;
162 uint32_t fHash;
163 };
164
165 struct Entry {
166 Program fProgram;
167 HashKey fKey;
168 uint32_t fLRUStamp;
169 };
170
171 // if hash bits is changed, need to change hash function
172 GrTHashTable<Entry, HashKey, 8> fHashCache;
173
174 static const int MAX_ENTRIES = 16;
175 Entry fEntries[MAX_ENTRIES];
176 int fCount;
177 uint32_t fCurrLRUStamp;
178
179public:
180 ProgramCache() {
181 fCount = 0;
182 fCurrLRUStamp = 0;
183 }
184
185 ~ProgramCache() {
186 for (int i = 0; i < fCount; ++i) {
187 GrGpuGLShaders2::DeleteProgram(&fEntries[i].fProgram);
188 }
189 }
190
191 void abandon() {
192 fCount = 0;
193 }
194
195 void invalidateViewMatrices() {
196 for (int i = 0; i < fCount; ++i) {
197 // set to illegal matrix
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000198 fEntries[i].fProgram.fViewMatrix = GrMatrix::InvalidMatrix();
reed@google.comac10a2d2010-12-22 21:39:39 +0000199 }
200 }
201
202 Program* getProgram(const ProgramDesc& desc) {
203 HashKey key(desc);
204 Entry* entry = fHashCache.find(key);
205 if (NULL == entry) {
206 if (fCount < MAX_ENTRIES) {
207 entry = fEntries + fCount;
208 ++fCount;
209 } else {
210 GrAssert(MAX_ENTRIES == fCount);
211 entry = fEntries;
212 for (int i = 1; i < MAX_ENTRIES; ++i) {
213 if (fEntries[i].fLRUStamp < entry->fLRUStamp) {
214 entry = fEntries + i;
215 }
216 }
217 fHashCache.remove(entry->fKey, entry);
218 GrGpuGLShaders2::DeleteProgram(&entry->fProgram);
219 }
220 entry->fKey = key;
221 GrGpuGLShaders2::GenProgram(desc, &entry->fProgram);
222 fHashCache.insert(entry->fKey, entry);
223 }
224
225 entry->fLRUStamp = fCurrLRUStamp;
reed@google.comd2938db2011-01-28 20:54:15 +0000226 if (GR_UINT32_MAX == fCurrLRUStamp) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000227 // wrap around! just trash our LRU, one time hit.
228 for (int i = 0; i < fCount; ++i) {
229 fEntries[i].fLRUStamp = 0;
230 }
231 }
232 ++fCurrLRUStamp;
233 return &entry->fProgram;
234 }
235};
236
237GrGpuGLShaders2::ProgramCache::HashKey::HashKey() {
238}
239
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000240static inline uint32_t ror(uint32_t x) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000241 return (x >> 8) | (x << 24);
242}
243
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000244static inline uint32_t rol(uint32_t x) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000245 return (x << 8) | (x >> 24);
246}
247
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000248static inline uint32_t roh(uint32_t x) {
249 return (x << 16) | (x >> 16);
250}
251
252static inline uint32_t swapouter(uint32_t x) {
bsalomon@google.com9dbdb402011-04-20 13:01:29 +0000253 return (x & 0x00ffff00) | (x << 24) | (x >> 24);
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000254}
255
reed@google.comac10a2d2010-12-22 21:39:39 +0000256GrGpuGLShaders2::ProgramCache::HashKey::HashKey(const ProgramDesc& desc) {
257 fDesc = desc;
258 // if you change the size of the desc, need to update the hash function
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000259 GR_STATIC_ASSERT(20 == sizeof(ProgramDesc));
reed@google.comac10a2d2010-12-22 21:39:39 +0000260
reed@google.com38690072011-01-26 01:44:18 +0000261 uint32_t* d = GrTCast<uint32_t*>(&fDesc);
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000262 fHash = d[0] ^ ror(d[1]) ^ rol(d[2]) ^ roh(d[3]) ^ swapouter(d[4]);
reed@google.comac10a2d2010-12-22 21:39:39 +0000263}
264
265bool GrGpuGLShaders2::ProgramCache::HashKey::EQ(const Entry& entry,
266 const HashKey& key) {
267 return entry.fKey == key;
268}
269
270bool GrGpuGLShaders2::ProgramCache::HashKey::LT(const Entry& entry,
271 const HashKey& key) {
272 return entry.fKey < key;
273}
274
275bool GrGpuGLShaders2::ProgramCache::HashKey::operator ==(const HashKey& key) const {
276 return fDesc == key.fDesc;
277}
278
279bool GrGpuGLShaders2::ProgramCache::HashKey::operator <(const HashKey& key) const {
280 return memcmp(&fDesc, &key.fDesc, sizeof(HashKey)) < 0;
281}
282
283uint32_t GrGpuGLShaders2::ProgramCache::HashKey::getHash() const {
284 return fHash;
285}
286
reed@google.comac10a2d2010-12-22 21:39:39 +0000287struct GrGpuGLShaders2::ShaderCodeSegments {
288 GrSStringBuilder<256> fVSUnis;
289 GrSStringBuilder<256> fVSAttrs;
290 GrSStringBuilder<256> fVaryings;
291 GrSStringBuilder<256> fFSUnis;
292 GrSStringBuilder<512> fVSCode;
293 GrSStringBuilder<512> fFSCode;
294};
295// for variable names etc
296typedef GrSStringBuilder<16> GrTokenString;
297
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000298#if GR_GL_ATTRIBUTE_MATRICES
reed@google.comac10a2d2010-12-22 21:39:39 +0000299 #define VIEW_MATRIX_NAME "aViewM"
300#else
301 #define VIEW_MATRIX_NAME "uViewM"
302#endif
303
304#define POS_ATTR_NAME "aPosition"
305#define COL_ATTR_NAME "aColor"
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000306#define COL_UNI_NAME "uColor"
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000307
308static inline void tex_attr_name(int coordIdx, GrStringBuilder* s) {
309 *s = "aTexCoord";
310 s->appendInt(coordIdx);
311}
reed@google.comac10a2d2010-12-22 21:39:39 +0000312
313static inline const char* float_vector_type(int count) {
314 static const char* FLOAT_VECS[] = {"ERROR", "float", "vec2", "vec3", "vec4"};
reed@google.com38690072011-01-26 01:44:18 +0000315 GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(FLOAT_VECS));
reed@google.comac10a2d2010-12-22 21:39:39 +0000316 return FLOAT_VECS[count];
317}
318
319static inline const char* vector_homog_coord(int count) {
320 static const char* HOMOGS[] = {"ERROR", "", ".y", ".z", ".w"};
reed@google.com38690072011-01-26 01:44:18 +0000321 GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(HOMOGS));
reed@google.comac10a2d2010-12-22 21:39:39 +0000322 return HOMOGS[count];
323}
324
325static inline const char* vector_nonhomog_coords(int count) {
326 static const char* NONHOMOGS[] = {"ERROR", "", ".x", ".xy", ".xyz"};
reed@google.com38690072011-01-26 01:44:18 +0000327 GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(NONHOMOGS));
reed@google.comac10a2d2010-12-22 21:39:39 +0000328 return NONHOMOGS[count];
329}
330
331static inline const char* vector_all_coords(int count) {
332 static const char* ALL[] = {"ERROR", "", ".xy", ".xyz", ".xyzw"};
reed@google.com38690072011-01-26 01:44:18 +0000333 GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(ALL));
reed@google.comac10a2d2010-12-22 21:39:39 +0000334 return ALL[count];
335}
336
337static void tex_matrix_name(int stage, GrStringBuilder* s) {
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000338#if GR_GL_ATTRIBUTE_MATRICES
reed@google.comac10a2d2010-12-22 21:39:39 +0000339 *s = "aTexM";
340#else
341 *s = "uTexM";
342#endif
343 s->appendInt(stage);
344}
345
346static void sampler_name(int stage, GrStringBuilder* s) {
347 *s = "uSampler";
348 s->appendInt(stage);
349}
350
351static void stage_varying_name(int stage, GrStringBuilder* s) {
352 *s = "vStage";
353 s->appendInt(stage);
354}
355
356static void radial2_param_name(int stage, GrStringBuilder* s) {
357 *s = "uRadial2Params";
358 s->appendInt(stage);
359}
360
361static void radial2_varying_name(int stage, GrStringBuilder* s) {
362 *s = "vB";
363 s->appendInt(stage);
364}
365
366#include "GrRandom.h"
367
368void GrGpuGLShaders2::ProgramUnitTest() {
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000369
reed@google.comac10a2d2010-12-22 21:39:39 +0000370 static const int STAGE_OPTS[] = {
371 0,
372 StageDesc::kNoPerspective_OptFlagBit,
373 StageDesc::kIdentity_CoordMapping
374 };
375 static const int STAGE_MODULATES[] = {
376 StageDesc::kColor_Modulation,
377 StageDesc::kAlpha_Modulation
378 };
379 static const int STAGE_COORD_MAPPINGS[] = {
380 StageDesc::kIdentity_CoordMapping,
381 StageDesc::kRadialGradient_CoordMapping,
382 StageDesc::kSweepGradient_CoordMapping,
383 StageDesc::kRadial2Gradient_CoordMapping
384 };
385 ProgramDesc pdesc;
386 memset(&pdesc, 0, sizeof(pdesc));
387
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000388 static const int NUM_TESTS = 512;
reed@google.comac10a2d2010-12-22 21:39:39 +0000389
390 // GrRandoms nextU() values have patterns in the low bits
391 // So using nextU() % array_count might never take some values.
392 GrRandom random;
393 for (int t = 0; t < NUM_TESTS; ++t) {
bsalomon@google.com316f99232011-01-13 21:28:12 +0000394
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000395 pdesc.fVertexLayout = 0;
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000396 pdesc.fEmitsPointSize = random.nextF() > .5f;
397 float colorType = random.nextF();
398 if (colorType < 1.f / 3.f) {
399 pdesc.fColorType = ProgramDesc::kAttribute_ColorType;
400 } else if (colorType < 2.f / 3.f) {
401 pdesc.fColorType = ProgramDesc::kUniform_ColorType;
402 } else {
403 pdesc.fColorType = ProgramDesc::kNone_ColorType;
404 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000405 for (int s = 0; s < kNumStages; ++s) {
406 // enable the stage?
407 if (random.nextF() > .5f) {
408 // use separate tex coords?
409 if (random.nextF() > .5f) {
410 int t = (int)(random.nextF() * kMaxTexCoords);
411 pdesc.fVertexLayout |= StageTexCoordVertexLayoutBit(s, t);
412 } else {
413 pdesc.fVertexLayout |= StagePosAsTexCoordVertexLayoutBit(s);
414 }
415 }
416 // use text-formatted verts?
417 if (random.nextF() > .5f) {
418 pdesc.fVertexLayout |= kTextFormat_VertexLayoutBit;
419 }
420 }
421
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000422 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000423 int x;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000424 pdesc.fStages[s].fEnabled = VertexUsesStage(s, pdesc.fVertexLayout);
reed@google.comac10a2d2010-12-22 21:39:39 +0000425 x = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_OPTS));
426 pdesc.fStages[s].fOptFlags = STAGE_OPTS[x];
427 x = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_MODULATES));
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000428 pdesc.fStages[s].fModulation = (StageDesc::Modulation) STAGE_MODULATES[x];
reed@google.comac10a2d2010-12-22 21:39:39 +0000429 x = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_COORD_MAPPINGS));
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000430 pdesc.fStages[s].fCoordMapping = (StageDesc::CoordMapping) STAGE_COORD_MAPPINGS[x];
reed@google.comac10a2d2010-12-22 21:39:39 +0000431 }
432 Program program;
433 GenProgram(pdesc, &program);
434 DeleteProgram(&program);
435 }
436}
437
438void GrGpuGLShaders2::GenStageCode(int stageNum,
439 const StageDesc& desc,
440 const char* fsInColor, // NULL means no incoming color
441 const char* fsOutColor,
442 const char* vsInCoord,
443 ShaderCodeSegments* segments,
444 StageUniLocations* locations) {
445
446 GrAssert(stageNum >= 0 && stageNum <= 9);
447
448 GrTokenString varyingName;
449 stage_varying_name(stageNum, &varyingName);
450
451 // First decide how many coords are needed to access the texture
452 // Right now it's always 2 but we could start using 1D textures for
453 // gradients.
454 static const int coordDims = 2;
455 int varyingDims;
456 /// Vertex Shader Stuff
457
458 // decide whether we need a matrix to transform texture coords
459 // and whether the varying needs a perspective coord.
460 GrTokenString texMName;
461 tex_matrix_name(stageNum, &texMName);
462 if (desc.fOptFlags & StageDesc::kIdentityMatrix_OptFlagBit) {
463 varyingDims = coordDims;
464 } else {
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000465 #if GR_GL_ATTRIBUTE_MATRICES
reed@google.comac10a2d2010-12-22 21:39:39 +0000466 segments->fVSAttrs += "attribute mat3 ";
467 segments->fVSAttrs += texMName;
468 segments->fVSAttrs += ";\n";
469 #else
470 segments->fVSUnis += "uniform mat3 ";
471 segments->fVSUnis += texMName;
472 segments->fVSUnis += ";\n";
473 locations->fTextureMatrixUni = 1;
474 #endif
475 if (desc.fOptFlags & StageDesc::kNoPerspective_OptFlagBit) {
476 varyingDims = coordDims;
477 } else {
478 varyingDims = coordDims + 1;
479 }
480 }
481
482 GrTokenString samplerName;
483 sampler_name(stageNum, &samplerName);
484 segments->fFSUnis += "uniform sampler2D ";
485 segments->fFSUnis += samplerName;
486 segments->fFSUnis += ";\n";
487 locations->fSamplerUni = 1;
488
489 segments->fVaryings += "varying ";
490 segments->fVaryings += float_vector_type(varyingDims);
491 segments->fVaryings += " ";
492 segments->fVaryings += varyingName;
493 segments->fVaryings += ";\n";
494
495 if (desc.fOptFlags & StageDesc::kIdentityMatrix_OptFlagBit) {
496 GrAssert(varyingDims == coordDims);
497 segments->fVSCode += "\t";
498 segments->fVSCode += varyingName;
499 segments->fVSCode += " = ";
500 segments->fVSCode += vsInCoord;
501 segments->fVSCode += ";\n";
502 } else {
503 segments->fVSCode += "\t";
504 segments->fVSCode += varyingName;
505 segments->fVSCode += " = (";
506 segments->fVSCode += texMName;
507 segments->fVSCode += " * vec3(";
508 segments->fVSCode += vsInCoord;
509 segments->fVSCode += ", 1))";
510 segments->fVSCode += vector_all_coords(varyingDims);
511 segments->fVSCode += ";\n";
512 }
513
514 GrTokenString radial2ParamsName;
515 radial2_param_name(stageNum, &radial2ParamsName);
516 // for radial grads without perspective we can pass the linear
517 // part of the quadratic as a varying.
518 GrTokenString radial2VaryingName;
519 radial2_varying_name(stageNum, &radial2VaryingName);
520
521 if (StageDesc::kRadial2Gradient_CoordMapping == desc.fCoordMapping) {
522
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000523 segments->fVSUnis += "uniform ";
524 segments->fVSUnis += GrPrecision();
525 segments->fVSUnis += " float ";
reed@google.comac10a2d2010-12-22 21:39:39 +0000526 segments->fVSUnis += radial2ParamsName;
527 segments->fVSUnis += "[6];\n";
528
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000529 segments->fFSUnis += "uniform ";
530 segments->fFSUnis += GrPrecision();
531 segments->fFSUnis += " float ";
reed@google.comac10a2d2010-12-22 21:39:39 +0000532 segments->fFSUnis += radial2ParamsName;
533 segments->fFSUnis += "[6];\n";
534 locations->fRadial2Uni = 1;
535
536 // if there is perspective we don't interpolate this
537 if (varyingDims == coordDims) {
538 GrAssert(2 == coordDims);
539 segments->fVaryings += "varying float ";
540 segments->fVaryings += radial2VaryingName;
541 segments->fVaryings += ";\n";
542
543 segments->fVSCode += "\t";
544 segments->fVSCode += radial2VaryingName;
545 segments->fVSCode += " = 2.0 * (";
546 segments->fVSCode += radial2ParamsName;
547 segments->fVSCode += "[2] * ";
548 segments->fVSCode += varyingName;
549 segments->fVSCode += ".x ";
550 segments->fVSCode += " - ";
551 segments->fVSCode += radial2ParamsName;
552 segments->fVSCode += "[3]);\n";
553 }
554 }
555
556 /// Fragment Shader Stuff
557 GrTokenString fsCoordName;
558 // function used to access the shader, may be made projective
559 GrTokenString texFunc("texture2D");
560 if (desc.fOptFlags & (StageDesc::kIdentityMatrix_OptFlagBit |
561 StageDesc::kNoPerspective_OptFlagBit)) {
562 GrAssert(varyingDims == coordDims);
563 fsCoordName = varyingName;
564 } else {
565 // if we have to do some non-matrix op on the varyings to get
566 // our final tex coords then when in perspective we have to
567 // do an explicit divide
568 if (StageDesc::kIdentity_CoordMapping == desc.fCoordMapping) {
569 texFunc += "Proj";
570 fsCoordName = varyingName;
571 } else {
572 fsCoordName = "tCoord";
573 fsCoordName.appendInt(stageNum);
574
575 segments->fFSCode += "\t";
576 segments->fFSCode += float_vector_type(coordDims);
577 segments->fFSCode += " ";
578 segments->fFSCode += fsCoordName;
579 segments->fFSCode += " = ";
580 segments->fFSCode += varyingName;
581 segments->fFSCode += vector_nonhomog_coords(varyingDims);
582 segments->fFSCode += " / ";
583 segments->fFSCode += varyingName;
584 segments->fFSCode += vector_homog_coord(varyingDims);
585 segments->fFSCode += ";\n";
586 }
587 }
588
589 GrSStringBuilder<96> sampleCoords;
590 switch (desc.fCoordMapping) {
591 case StageDesc::kIdentity_CoordMapping:
592 sampleCoords = fsCoordName;
593 break;
594 case StageDesc::kSweepGradient_CoordMapping:
595 sampleCoords = "vec2(atan(-";
596 sampleCoords += fsCoordName;
597 sampleCoords += ".y, -";
598 sampleCoords += fsCoordName;
599 sampleCoords += ".x)*0.1591549430918 + 0.5, 0.5)";
600 break;
601 case StageDesc::kRadialGradient_CoordMapping:
602 sampleCoords = "vec2(length(";
603 sampleCoords += fsCoordName;
604 sampleCoords += ".xy), 0.5)";
605 break;
606 case StageDesc::kRadial2Gradient_CoordMapping: {
607 GrTokenString cName = "c";
608 GrTokenString ac4Name = "ac4";
609 GrTokenString rootName = "root";
610
611 cName.appendInt(stageNum);
612 ac4Name.appendInt(stageNum);
613 rootName.appendInt(stageNum);
614
615 GrTokenString bVar;
616 if (coordDims == varyingDims) {
617 bVar = radial2VaryingName;
618 GrAssert(2 == varyingDims);
619 } else {
620 GrAssert(3 == varyingDims);
621 bVar = "b";
622 bVar.appendInt(stageNum);
623 segments->fFSCode += "\tfloat ";
624 segments->fFSCode += bVar;
625 segments->fFSCode += " = 2.0 * (";
626 segments->fFSCode += radial2ParamsName;
627 segments->fFSCode += "[2] * ";
628 segments->fFSCode += fsCoordName;
629 segments->fFSCode += ".x ";
630 segments->fFSCode += " - ";
631 segments->fFSCode += radial2ParamsName;
632 segments->fFSCode += "[3]);\n";
633 }
634
635 segments->fFSCode += "\tfloat ";
636 segments->fFSCode += cName;
637 segments->fFSCode += " = dot(";
638 segments->fFSCode += fsCoordName;
639 segments->fFSCode += ", ";
640 segments->fFSCode += fsCoordName;
641 segments->fFSCode += ") + ";
642 segments->fFSCode += " - ";
643 segments->fFSCode += radial2ParamsName;
644 segments->fFSCode += "[4];\n";
645
646 segments->fFSCode += "\tfloat ";
647 segments->fFSCode += ac4Name;
648 segments->fFSCode += " = ";
649 segments->fFSCode += radial2ParamsName;
650 segments->fFSCode += "[0] * 4.0 * ";
651 segments->fFSCode += cName;
652 segments->fFSCode += ";\n";
653
654 segments->fFSCode += "\tfloat ";
655 segments->fFSCode += rootName;
656 segments->fFSCode += " = sqrt(abs(";
657 segments->fFSCode += bVar;
658 segments->fFSCode += " * ";
659 segments->fFSCode += bVar;
660 segments->fFSCode += " - ";
661 segments->fFSCode += ac4Name;
662 segments->fFSCode += "));\n";
663
664 sampleCoords = "vec2((-";
665 sampleCoords += bVar;
666 sampleCoords += " + ";
667 sampleCoords += radial2ParamsName;
668 sampleCoords += "[5] * ";
669 sampleCoords += rootName;
670 sampleCoords += ") * ";
671 sampleCoords += radial2ParamsName;
672 sampleCoords += "[1], 0.5)\n";
673 break;}
674 };
675
676 segments->fFSCode += "\t";
677 segments->fFSCode += fsOutColor;
678 segments->fFSCode += " = ";
679 if (NULL != fsInColor) {
680 segments->fFSCode += fsInColor;
681 segments->fFSCode += " * ";
682 }
683 segments->fFSCode += texFunc;
684 segments->fFSCode += "(";
685 segments->fFSCode += samplerName;
686 segments->fFSCode += ", ";
687 segments->fFSCode += sampleCoords;
688 segments->fFSCode += ")";
689 if (desc.fModulation == StageDesc::kAlpha_Modulation) {
690 segments->fFSCode += ".aaaa";
691 }
692 segments->fFSCode += ";\n";
693
694}
695
696void GrGpuGLShaders2::GenProgram(const ProgramDesc& desc,
697 Program* program) {
698
699 ShaderCodeSegments segments;
700 const uint32_t& layout = desc.fVertexLayout;
701
702 memset(&program->fUniLocations, 0, sizeof(UniLocations));
703
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000704#if GR_GL_ATTRIBUTE_MATRICES
705 segments.fVSAttrs += "attribute mat3 " VIEW_MATRIX_NAME ";\n";
reed@google.comac10a2d2010-12-22 21:39:39 +0000706#else
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000707 segments.fVSUnis += "uniform mat3 " VIEW_MATRIX_NAME ";\n";
reed@google.comac10a2d2010-12-22 21:39:39 +0000708#endif
709 segments.fVSAttrs += "attribute vec2 " POS_ATTR_NAME ";\n";
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000710
711 segments.fVSCode += "void main() {\n"
712 "\tvec3 pos3 = " VIEW_MATRIX_NAME " * vec3(" POS_ATTR_NAME ", 1);\n"
713 "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n";
714
715 // incoming color to current stage being processed.
716 GrTokenString inColor;
717
718 switch (desc.fColorType) {
719 case ProgramDesc::kAttribute_ColorType:
reed@google.comac10a2d2010-12-22 21:39:39 +0000720 segments.fVSAttrs += "attribute vec4 " COL_ATTR_NAME ";\n";
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000721 segments.fVaryings += "varying vec4 vColor;\n";
reed@google.comac10a2d2010-12-22 21:39:39 +0000722 segments.fVSCode += "\tvColor = " COL_ATTR_NAME ";\n";
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000723 inColor = "vColor";
724 break;
725 case ProgramDesc::kUniform_ColorType:
726 segments.fFSUnis += "uniform vec4 " COL_UNI_NAME ";\n";
727 inColor = COL_UNI_NAME;
728 break;
729 case ProgramDesc::kNone_ColorType:
730 inColor = "";
731 break;
reed@google.comac10a2d2010-12-22 21:39:39 +0000732 }
733
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000734 if (desc.fEmitsPointSize){
reed@google.comac10a2d2010-12-22 21:39:39 +0000735 segments.fVSCode += "\tgl_PointSize = 1.0;\n";
736 }
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000737 segments.fFSCode += "void main() {\n";
reed@google.comac10a2d2010-12-22 21:39:39 +0000738
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000739 // add texture coordinates that are used to the list of vertex attr decls
740 GrTokenString texCoordAttrs[kMaxTexCoords];
741 for (int t = 0; t < kMaxTexCoords; ++t) {
742 if (VertexUsesTexCoordIdx(t, layout)) {
743 tex_attr_name(t, texCoordAttrs + t);
744
745 segments.fVSAttrs += "attribute vec2 ";
746 segments.fVSAttrs += texCoordAttrs[t];
747 segments.fVSAttrs += ";\n";
748 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000749 }
750
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000751 // for each enabled stage figure out what the input coordinates are
752 // and count the number of stages in use.
753 const char* stageInCoords[kNumStages];
reed@google.comac10a2d2010-12-22 21:39:39 +0000754 int numActiveStages = 0;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000755
756 for (int s = 0; s < kNumStages; ++s) {
757 if (desc.fStages[s].fEnabled) {
758 if (StagePosAsTexCoordVertexLayoutBit(s) & layout) {
759 stageInCoords[s] = POS_ATTR_NAME;
760 } else {
761 int tcIdx = VertexTexCoordsForStage(s, layout);
762 // we better have input tex coordinates if stage is enabled.
763 GrAssert(tcIdx >= 0);
764 GrAssert(texCoordAttrs[tcIdx].length());
765 stageInCoords[s] = texCoordAttrs[tcIdx].cstr();
766 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000767 ++numActiveStages;
768 }
769 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000770
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000771 // if we have active stages string them together, feeding the output color
772 // of each to the next and generating code for each stage.
773 if (numActiveStages) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000774 int currActiveStage = 0;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000775 for (int s = 0; s < kNumStages; ++s) {
776 if (desc.fStages[s].fEnabled) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000777 GrTokenString outColor;
778 if (currActiveStage < (numActiveStages - 1)) {
779 outColor = "color";
780 outColor.appendInt(currActiveStage);
781 segments.fFSCode += "\tvec4 ";
782 segments.fFSCode += outColor;
783 segments.fFSCode += ";\n";
784 } else {
785 outColor = "gl_FragColor";
786 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000787 GenStageCode(s,
788 desc.fStages[s],
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000789 inColor.length() ? inColor.cstr() : NULL,
reed@google.comac10a2d2010-12-22 21:39:39 +0000790 outColor.cstr(),
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000791 stageInCoords[s],
reed@google.comac10a2d2010-12-22 21:39:39 +0000792 &segments,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000793 &program->fUniLocations.fStages[s]);
reed@google.comac10a2d2010-12-22 21:39:39 +0000794 ++currActiveStage;
795 inColor = outColor;
reed@google.comac10a2d2010-12-22 21:39:39 +0000796 }
797 }
798 } else {
799 segments.fFSCode += "\tgl_FragColor = ";
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000800 if (inColor.length()) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000801 segments.fFSCode += inColor;
802 } else {
803 segments.fFSCode += "vec4(1,1,1,1)";
804 }
805 segments.fFSCode += ";\n";
806 }
807 segments.fFSCode += "}\n";
808 segments.fVSCode += "}\n";
809
810
811 const char* strings[4];
812 int lengths[4];
813 int stringCnt = 0;
814
815 if (segments.fVSUnis.length()) {
816 strings[stringCnt] = segments.fVSUnis.cstr();
817 lengths[stringCnt] = segments.fVSUnis.length();
818 ++stringCnt;
819 }
820 if (segments.fVSAttrs.length()) {
821 strings[stringCnt] = segments.fVSAttrs.cstr();
822 lengths[stringCnt] = segments.fVSAttrs.length();
823 ++stringCnt;
824 }
825 if (segments.fVaryings.length()) {
826 strings[stringCnt] = segments.fVaryings.cstr();
827 lengths[stringCnt] = segments.fVaryings.length();
828 ++stringCnt;
829 }
830
831 GrAssert(segments.fVSCode.length());
832 strings[stringCnt] = segments.fVSCode.cstr();
833 lengths[stringCnt] = segments.fVSCode.length();
834 ++stringCnt;
835
836#if PRINT_SHADERS
837 GrPrintf("%s%s%s%s\n",
838 segments.fVSUnis.cstr(),
839 segments.fVSAttrs.cstr(),
840 segments.fVaryings.cstr(),
841 segments.fVSCode.cstr());
842#endif
twiz@google.com0f31ca72011-03-18 17:38:11 +0000843 program->fVShaderID = CompileShader(GR_GL_VERTEX_SHADER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000844 stringCnt,
845 strings,
846 lengths);
847
848 stringCnt = 0;
849
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000850 if (strlen(GrShaderPrecision()) > 1) {
851 strings[stringCnt] = GrShaderPrecision();
852 lengths[stringCnt] = strlen(GrShaderPrecision());
reed@google.comac10a2d2010-12-22 21:39:39 +0000853 ++stringCnt;
854 }
855 if (segments.fFSUnis.length()) {
856 strings[stringCnt] = segments.fFSUnis.cstr();
857 lengths[stringCnt] = segments.fFSUnis.length();
858 ++stringCnt;
859 }
860 if (segments.fVaryings.length()) {
861 strings[stringCnt] = segments.fVaryings.cstr();
862 lengths[stringCnt] = segments.fVaryings.length();
863 ++stringCnt;
864 }
865
866 GrAssert(segments.fFSCode.length());
867 strings[stringCnt] = segments.fFSCode.cstr();
868 lengths[stringCnt] = segments.fFSCode.length();
869 ++stringCnt;
870
871#if PRINT_SHADERS
872 GrPrintf("%s%s%s%s\n",
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000873 GrShaderPrecision(),
reed@google.comac10a2d2010-12-22 21:39:39 +0000874 segments.fFSUnis.cstr(),
875 segments.fVaryings.cstr(),
876 segments.fFSCode.cstr());
877#endif
twiz@google.com0f31ca72011-03-18 17:38:11 +0000878 program->fFShaderID = CompileShader(GR_GL_FRAGMENT_SHADER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000879 stringCnt,
880 strings,
881 lengths);
882
883 program->fProgramID = GR_GL(CreateProgram());
twiz@google.com0f31ca72011-03-18 17:38:11 +0000884 const GrGLint& progID = program->fProgramID;
reed@google.comac10a2d2010-12-22 21:39:39 +0000885
886 GR_GL(AttachShader(progID, program->fVShaderID));
887 GR_GL(AttachShader(progID, program->fFShaderID));
888
889 // Bind the attrib locations to same values for all shaders
890 GR_GL(BindAttribLocation(progID, POS_ATTR_LOCATION, POS_ATTR_NAME));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000891 for (int t = 0; t < kMaxTexCoords; ++t) {
892 if (texCoordAttrs[t].length()) {
bsalomon@google.com316f99232011-01-13 21:28:12 +0000893 GR_GL(BindAttribLocation(progID,
894 TEX_ATTR_LOCATION(t),
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000895 texCoordAttrs[t].cstr()));
896 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000897 }
898
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000899#if GR_GL_ATTRIBUTE_MATRICES
reed@google.comac10a2d2010-12-22 21:39:39 +0000900 // set unis to a bogus value so that checks against -1 before
901 // flushing will pass.
902 GR_GL(BindAttribLocation(progID,
903 VIEWMAT_ATTR_LOCATION,
904 VIEW_MATRIX_NAME));
905
906 program->fUniLocations.fViewMatrixUni = BOGUS_MATRIX_UNI_LOCATION;
907
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000908 for (int s = 0; s < kNumStages; ++s) {
909 if (desc.fStages[s].fEnabled) {
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000910 GrStringBuilder matName;
911 tex_matrix_name(s, &matName);
reed@google.comac10a2d2010-12-22 21:39:39 +0000912 GR_GL(BindAttribLocation(progID,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000913 TEXMAT_ATTR_LOCATION(s),
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000914 matName.cstr()));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000915 program->fUniLocations.fStages[s].fTextureMatrixUni =
reed@google.comac10a2d2010-12-22 21:39:39 +0000916 BOGUS_MATRIX_UNI_LOCATION;
917 }
918 }
919#endif
920
921 GR_GL(BindAttribLocation(progID, COL_ATTR_LOCATION, COL_ATTR_NAME));
922
923 GR_GL(LinkProgram(progID));
924
twiz@google.com0f31ca72011-03-18 17:38:11 +0000925 GrGLint linked = GR_GL_INIT_ZERO;
926 GR_GL(GetProgramiv(progID, GR_GL_LINK_STATUS, &linked));
reed@google.comac10a2d2010-12-22 21:39:39 +0000927 if (!linked) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000928 GrGLint infoLen = GR_GL_INIT_ZERO;
929 GR_GL(GetProgramiv(progID, GR_GL_INFO_LOG_LENGTH, &infoLen));
reed@google.comac10a2d2010-12-22 21:39:39 +0000930 GrAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
931 if (infoLen > 0) {
932 GR_GL(GetProgramInfoLog(progID,
933 infoLen+1,
934 NULL,
935 (char*)log.get()));
936 GrPrintf((char*)log.get());
937 }
938 GrAssert(!"Error linking program");
939 GR_GL(DeleteProgram(progID));
940 program->fProgramID = 0;
941 return;
942 }
943
944 // Get uniform locations
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000945#if !GR_GL_ATTRIBUTE_MATRICES
reed@google.comac10a2d2010-12-22 21:39:39 +0000946 program->fUniLocations.fViewMatrixUni =
947 GR_GL(GetUniformLocation(progID, VIEW_MATRIX_NAME));
948 GrAssert(-1 != program->fUniLocations.fViewMatrixUni);
949#endif
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000950 if (ProgramDesc::kUniform_ColorType == desc.fColorType) {
951 program->fUniLocations.fColorUni =
952 GR_GL(GetUniformLocation(progID, COL_UNI_NAME));
953 GrAssert(-1 != program->fUniLocations.fColorUni);
954 } else {
955 program->fUniLocations.fColorUni = -1;
956 }
957
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000958 for (int s = 0; s < kNumStages; ++s) {
959 StageUniLocations& locations = program->fUniLocations.fStages[s];
960 if (desc.fStages[s].fEnabled) {
bsalomon@google.com4be283f2011-04-19 21:15:09 +0000961#if !GR_GL_ATTRIBUTE_MATRICES
reed@google.comac10a2d2010-12-22 21:39:39 +0000962 if (locations.fTextureMatrixUni) {
963 GrTokenString texMName;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000964 tex_matrix_name(s, &texMName);
reed@google.comac10a2d2010-12-22 21:39:39 +0000965 locations.fTextureMatrixUni = GR_GL(GetUniformLocation(
966 progID,
967 texMName.cstr()));
968 GrAssert(-1 != locations.fTextureMatrixUni);
969 } else {
970 locations.fTextureMatrixUni = -1;
971
972 }
973#endif
974
975 if (locations.fSamplerUni) {
976 GrTokenString samplerName;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000977 sampler_name(s, &samplerName);
reed@google.comac10a2d2010-12-22 21:39:39 +0000978 locations.fSamplerUni = GR_GL(GetUniformLocation(
979 progID,
980 samplerName.cstr()));
981 GrAssert(-1 != locations.fSamplerUni);
982 } else {
983 locations.fSamplerUni = -1;
984 }
985
986 if (locations.fRadial2Uni) {
987 GrTokenString radial2ParamName;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000988 radial2_param_name(s, &radial2ParamName);
reed@google.comac10a2d2010-12-22 21:39:39 +0000989 locations.fRadial2Uni = GR_GL(GetUniformLocation(
990 progID,
991 radial2ParamName.cstr()));
992 GrAssert(-1 != locations.fRadial2Uni);
993 } else {
994 locations.fRadial2Uni = -1;
995 }
996 } else {
997 locations.fSamplerUni = -1;
998 locations.fRadial2Uni = -1;
999 locations.fTextureMatrixUni = -1;
1000 }
1001 }
1002 GR_GL(UseProgram(progID));
1003
1004 // init sampler unis and set bogus values for state tracking
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001005 for (int s = 0; s < kNumStages; ++s) {
1006 if (-1 != program->fUniLocations.fStages[s].fSamplerUni) {
1007 GR_GL(Uniform1i(program->fUniLocations.fStages[s].fSamplerUni, s));
reed@google.comac10a2d2010-12-22 21:39:39 +00001008 }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001009 program->fTextureMatrices[s] = GrMatrix::InvalidMatrix();
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001010 program->fRadial2CenterX1[s] = GR_ScalarMax;
1011 program->fRadial2Radius0[s] = -GR_ScalarMax;
bsalomon@google.com4be283f2011-04-19 21:15:09 +00001012 program->fColor = GrColor_ILLEGAL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001013 }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001014 program->fViewMatrix = GrMatrix::InvalidMatrix();
reed@google.comac10a2d2010-12-22 21:39:39 +00001015}
1016
bsalomon@google.comffca4002011-02-22 20:34:01 +00001017void GrGpuGLShaders2::getProgramDesc(GrPrimitiveType primType, ProgramDesc* desc) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001018
1019 // Must initialize all fields or cache will have false negatives!
1020 desc->fVertexLayout = fGeometrySrc.fVertexLayout;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001021
bsalomon@google.com4be283f2011-04-19 21:15:09 +00001022 desc->fEmitsPointSize = kPoints_PrimitiveType == primType;
1023
1024 bool requiresAttributeColors = desc->fVertexLayout & kColor_VertexLayoutBit;
1025 // fColorType records how colors are specified for the program. Strip
1026 // the bit from the layout to avoid false negatives when searching for an
1027 // existing program in the cache.
1028 desc->fVertexLayout &= ~(kColor_VertexLayoutBit);
1029
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001030#if GR_AGGRESSIVE_SHADER_OPTS
bsalomon@google.com4be283f2011-04-19 21:15:09 +00001031 if (!requiresAttributeColors && (0xffffffff == fCurrDrawState.fColor)) {
1032 desc->fColorType = ProgramDesc::kNone_ColorType;
1033 } else
bsalomon@google.comd16983b2011-02-02 22:42:20 +00001034#endif
bsalomon@google.com4be283f2011-04-19 21:15:09 +00001035#if GR_GL_NO_CONSTANT_ATTRIBUTES
1036 if (!requiresAttributeColors) {
1037 desc->fColorType = ProgramDesc::kUniform_ColorType;
1038 } else
1039#endif
1040 {
bsalomon@google.com6a77cc52011-04-28 17:33:34 +00001041 if (requiresAttributeColors) {} // suppress unused var warning
bsalomon@google.com4be283f2011-04-19 21:15:09 +00001042 desc->fColorType = ProgramDesc::kAttribute_ColorType;
1043 }
bsalomon@google.comd16983b2011-02-02 22:42:20 +00001044
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001045 for (int s = 0; s < kNumStages; ++s) {
1046 StageDesc& stage = desc->fStages[s];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001047
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001048 stage.fEnabled = this->isStageEnabled(s);
reed@google.comac10a2d2010-12-22 21:39:39 +00001049
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001050 if (stage.fEnabled) {
1051 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
1052 GrAssert(NULL != texture);
1053 // we matrix to invert when orientation is TopDown, so make sure
1054 // we aren't in that case before flagging as identity.
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001055 if (TextureMatrixIsIdentity(texture, fCurrDrawState.fSamplerStates[s])) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001056 stage.fOptFlags = StageDesc::kIdentityMatrix_OptFlagBit;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001057 } else if (!getSamplerMatrix(s).hasPerspective()) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001058 stage.fOptFlags = StageDesc::kNoPerspective_OptFlagBit;
1059 } else {
1060 stage.fOptFlags = 0;
1061 }
1062 switch (fCurrDrawState.fSamplerStates[s].getSampleMode()) {
1063 case GrSamplerState::kNormal_SampleMode:
1064 stage.fCoordMapping = StageDesc::kIdentity_CoordMapping;
1065 break;
1066 case GrSamplerState::kRadial_SampleMode:
1067 stage.fCoordMapping = StageDesc::kRadialGradient_CoordMapping;
1068 break;
1069 case GrSamplerState::kRadial2_SampleMode:
1070 stage.fCoordMapping = StageDesc::kRadial2Gradient_CoordMapping;
1071 break;
1072 case GrSamplerState::kSweep_SampleMode:
1073 stage.fCoordMapping = StageDesc::kSweepGradient_CoordMapping;
1074 break;
1075 default:
1076 GrAssert(!"Unexpected sample mode!");
1077 break;
1078 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001079 if (GrPixelConfigIsAlphaOnly(texture->config())) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001080 stage.fModulation = StageDesc::kAlpha_Modulation;
1081 } else {
1082 stage.fModulation = StageDesc::kColor_Modulation;
1083 }
1084 } else {
1085 stage.fOptFlags = 0;
1086 stage.fCoordMapping = (StageDesc::CoordMapping)0;
1087 stage.fModulation = (StageDesc::Modulation)0;
1088 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001089 }
1090}
1091
twiz@google.com0f31ca72011-03-18 17:38:11 +00001092GrGLuint GrGpuGLShaders2::CompileShader(GrGLenum type,
1093 int stringCnt,
1094 const char** strings,
1095 int* stringLengths) {
1096 GrGLuint shader = GR_GL(CreateShader(type));
reed@google.comac10a2d2010-12-22 21:39:39 +00001097 if (0 == shader) {
1098 return 0;
1099 }
1100
twiz@google.com0f31ca72011-03-18 17:38:11 +00001101 GrGLint compiled = GR_GL_INIT_ZERO;
reed@google.comac10a2d2010-12-22 21:39:39 +00001102 GR_GL(ShaderSource(shader, stringCnt, strings, stringLengths));
1103 GR_GL(CompileShader(shader));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001104 GR_GL(GetShaderiv(shader, GR_GL_COMPILE_STATUS, &compiled));
reed@google.comac10a2d2010-12-22 21:39:39 +00001105
1106 if (!compiled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001107 GrGLint infoLen = GR_GL_INIT_ZERO;
1108 GR_GL(GetShaderiv(shader, GR_GL_INFO_LOG_LENGTH, &infoLen));
reed@google.comac10a2d2010-12-22 21:39:39 +00001109 GrAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
1110 if (infoLen > 0) {
1111 GR_GL(GetShaderInfoLog(shader, infoLen+1, NULL, (char*)log.get()));
1112 for (int i = 0; i < stringCnt; ++i) {
1113 if (NULL == stringLengths || stringLengths[i] < 0) {
1114 GrPrintf(strings[i]);
1115 } else {
1116 GrPrintf("%.*s", stringLengths[i], strings[i]);
1117 }
1118 }
1119 GrPrintf("\n%s", log.get());
1120 }
1121 GrAssert(!"Shader compilation failed!");
1122 GR_GL(DeleteShader(shader));
1123 return 0;
1124 }
1125 return shader;
1126}
1127
1128void GrGpuGLShaders2::DeleteProgram(Program* program) {
1129 GR_GL(DeleteShader(program->fVShaderID));
1130 GR_GL(DeleteShader(program->fFShaderID));
1131 GR_GL(DeleteProgram(program->fProgramID));
1132 GR_DEBUGCODE(memset(program, 0, sizeof(Program)));
1133}
1134
1135
1136GrGpuGLShaders2::GrGpuGLShaders2() {
1137
reed@google.comac10a2d2010-12-22 21:39:39 +00001138 fProgram = NULL;
1139 fProgramCache = new ProgramCache();
1140
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001141#if 0
reed@google.comac10a2d2010-12-22 21:39:39 +00001142 ProgramUnitTest();
1143#endif
1144}
1145
1146GrGpuGLShaders2::~GrGpuGLShaders2() {
1147 delete fProgramCache;
1148}
1149
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001150const GrMatrix& GrGpuGLShaders2::getHWSamplerMatrix(int stage) {
bsalomon@google.com4be283f2011-04-19 21:15:09 +00001151#if GR_GL_ATTRIBUTE_MATRICES
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001152 return fHWDrawState.fSamplerStates[stage].getMatrix();
1153#else
1154 return fProgram->fTextureMatrices[stage];
1155#endif
1156}
1157
1158void GrGpuGLShaders2::recordHWSamplerMatrix(int stage, const GrMatrix& matrix){
bsalomon@google.com4be283f2011-04-19 21:15:09 +00001159#if GR_GL_ATTRIBUTE_MATRICES
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001160 fHWDrawState.fSamplerStates[stage].setMatrix(matrix);
1161#else
1162 fProgram->fTextureMatrices[stage] = matrix;
1163#endif
1164}
1165
reed@google.comac10a2d2010-12-22 21:39:39 +00001166void GrGpuGLShaders2::resetContext() {
reed@google.comac10a2d2010-12-22 21:39:39 +00001167
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001168 INHERITED::resetContext();
1169
reed@google.comac10a2d2010-12-22 21:39:39 +00001170 fHWGeometryState.fVertexLayout = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001171 fHWGeometryState.fVertexOffset = ~0;
reed@google.comac10a2d2010-12-22 21:39:39 +00001172 GR_GL(DisableVertexAttribArray(COL_ATTR_LOCATION));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001173 for (int t = 0; t < kMaxTexCoords; ++t) {
1174 GR_GL(DisableVertexAttribArray(TEX_ATTR_LOCATION(t)));
1175 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001176 GR_GL(EnableVertexAttribArray(POS_ATTR_LOCATION));
1177
1178 fHWProgramID = 0;
1179}
1180
1181void GrGpuGLShaders2::flushViewMatrix() {
1182 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1183 GrMatrix m (
1184 GrIntToScalar(2) / fCurrDrawState.fRenderTarget->width(), 0, -GR_Scalar1,
1185 0,-GrIntToScalar(2) / fCurrDrawState.fRenderTarget->height(), GR_Scalar1,
1186 0, 0, GrMatrix::I()[8]);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001187 m.setConcat(m, fCurrDrawState.fViewMatrix);
reed@google.comac10a2d2010-12-22 21:39:39 +00001188
1189 // ES doesn't allow you to pass true to the transpose param,
1190 // so do our own transpose
1191 GrScalar mt[] = {
1192 m[GrMatrix::kScaleX],
1193 m[GrMatrix::kSkewY],
1194 m[GrMatrix::kPersp0],
1195 m[GrMatrix::kSkewX],
1196 m[GrMatrix::kScaleY],
1197 m[GrMatrix::kPersp1],
1198 m[GrMatrix::kTransX],
1199 m[GrMatrix::kTransY],
1200 m[GrMatrix::kPersp2]
1201 };
bsalomon@google.com4be283f2011-04-19 21:15:09 +00001202#if GR_GL_ATTRIBUTE_MATRICES
bsalomon@google.com316f99232011-01-13 21:28:12 +00001203 GR_GL(VertexAttrib4fv(VIEWMAT_ATTR_LOCATION+0, mt+0));
1204 GR_GL(VertexAttrib4fv(VIEWMAT_ATTR_LOCATION+1, mt+3));
1205 GR_GL(VertexAttrib4fv(VIEWMAT_ATTR_LOCATION+2, mt+6));
reed@google.comac10a2d2010-12-22 21:39:39 +00001206#else
1207 GR_GL(UniformMatrix3fv(fProgram->fUniLocations.fViewMatrixUni,1,false,mt));
1208#endif
1209}
1210
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001211void GrGpuGLShaders2::flushTextureMatrix(int stage) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001212 GrAssert(NULL != fCurrDrawState.fTextures[stage]);
reed@google.comac10a2d2010-12-22 21:39:39 +00001213
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001214 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[stage];
1215
1216 GrMatrix m = getSamplerMatrix(stage);
1217 GrSamplerState::SampleMode mode =
bsalomon@google.come624caf2011-04-22 19:22:58 +00001218 fCurrDrawState.fSamplerStates[stage].getSampleMode();
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001219 AdjustTextureMatrix(texture, mode, &m);
reed@google.comac10a2d2010-12-22 21:39:39 +00001220
1221 // ES doesn't allow you to pass true to the transpose param,
1222 // so do our own transpose
1223 GrScalar mt[] = {
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001224 m[GrMatrix::kScaleX],
1225 m[GrMatrix::kSkewY],
1226 m[GrMatrix::kPersp0],
1227 m[GrMatrix::kSkewX],
1228 m[GrMatrix::kScaleY],
1229 m[GrMatrix::kPersp1],
1230 m[GrMatrix::kTransX],
1231 m[GrMatrix::kTransY],
1232 m[GrMatrix::kPersp2]
reed@google.comac10a2d2010-12-22 21:39:39 +00001233 };
bsalomon@google.com4be283f2011-04-19 21:15:09 +00001234#if GR_GL_ATTRIBUTE_MATRICES
bsalomon@google.com316f99232011-01-13 21:28:12 +00001235 GR_GL(VertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+0, mt+0));
1236 GR_GL(VertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+1, mt+3));
1237 GR_GL(VertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+2, mt+6));
reed@google.comac10a2d2010-12-22 21:39:39 +00001238#else
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001239 GR_GL(UniformMatrix3fv(fProgram->fUniLocations.fStages[stage].fTextureMatrixUni,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001240 1, false, mt));
reed@google.comac10a2d2010-12-22 21:39:39 +00001241#endif
1242}
1243
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001244void GrGpuGLShaders2::flushRadial2(int stage) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001245
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001246 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[stage];
reed@google.comac10a2d2010-12-22 21:39:39 +00001247
1248 GrScalar centerX1 = sampler.getRadial2CenterX1();
1249 GrScalar radius0 = sampler.getRadial2Radius0();
1250
1251 GrScalar a = GrMul(centerX1, centerX1) - GR_Scalar1;
1252
1253 float unis[6] = {
1254 GrScalarToFloat(a),
1255 1 / (2.f * unis[0]),
1256 GrScalarToFloat(centerX1),
1257 GrScalarToFloat(radius0),
1258 GrScalarToFloat(GrMul(radius0, radius0)),
1259 sampler.isRadial2PosRoot() ? 1.f : -1.f
1260 };
bsalomon@google.com316f99232011-01-13 21:28:12 +00001261 GR_GL(Uniform1fv(fProgram->fUniLocations.fStages[stage].fRadial2Uni,
1262 6,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001263 unis));
reed@google.comac10a2d2010-12-22 21:39:39 +00001264}
1265
bsalomon@google.com4be283f2011-04-19 21:15:09 +00001266void GrGpuGLShaders2::flushProgram(GrPrimitiveType type, ProgramDesc* desc) {
1267 getProgramDesc(type, desc);
1268 fProgram = fProgramCache->getProgram(*desc);
reed@google.comac10a2d2010-12-22 21:39:39 +00001269
1270 if (fHWProgramID != fProgram->fProgramID) {
1271 GR_GL(UseProgram(fProgram->fProgramID));
1272 fHWProgramID = fProgram->fProgramID;
1273#if GR_COLLECT_STATS
1274 ++fStats.fProgChngCnt;
1275#endif
1276 }
1277}
1278
bsalomon@google.com4be283f2011-04-19 21:15:09 +00001279void GrGpuGLShaders2::flushColor(const ProgramDesc& desc) {
1280 if (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) {
1281 // color will be specified per-vertex as an attribute
1282 // invalidate the const vertex attrib color
1283 fHWDrawState.fColor = GrColor_ILLEGAL;
1284 } else {
1285 switch (desc.fColorType) {
1286 case ProgramDesc::kAttribute_ColorType:
1287 if (fHWDrawState.fColor != fCurrDrawState.fColor) {
1288 // OpenGL ES only supports the float varities of glVertexAttrib
1289 float c[] = {
1290 GrColorUnpackR(fCurrDrawState.fColor) / 255.f,
1291 GrColorUnpackG(fCurrDrawState.fColor) / 255.f,
1292 GrColorUnpackB(fCurrDrawState.fColor) / 255.f,
1293 GrColorUnpackA(fCurrDrawState.fColor) / 255.f
1294 };
1295 GR_GL(VertexAttrib4fv(COL_ATTR_LOCATION, c));
1296 fHWDrawState.fColor = fCurrDrawState.fColor;
1297 }
1298 break;
1299 case ProgramDesc::kUniform_ColorType:
1300 if (fProgram->fColor != fCurrDrawState.fColor) {
1301 // OpenGL ES only supports the float varities of glVertexAttrib
1302 float c[] = {
1303 GrColorUnpackR(fCurrDrawState.fColor) / 255.f,
1304 GrColorUnpackG(fCurrDrawState.fColor) / 255.f,
1305 GrColorUnpackB(fCurrDrawState.fColor) / 255.f,
1306 GrColorUnpackA(fCurrDrawState.fColor) / 255.f
1307 };
1308 GrAssert(-1 != fProgram->fUniLocations.fColorUni);
1309 GR_GL(Uniform4fv(fProgram->fUniLocations.fColorUni, 1, c));
1310 fProgram->fColor = fCurrDrawState.fColor;
1311 }
1312 break;
1313 case ProgramDesc::kNone_ColorType:
1314 GrAssert(0xffffffff == fCurrDrawState.fColor);
1315 break;
1316 default:
1317 GrCrash("Unknown color type.");
1318 }
1319 }
1320}
1321
bsalomon@google.comffca4002011-02-22 20:34:01 +00001322bool GrGpuGLShaders2::flushGraphicsState(GrPrimitiveType type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001323
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001324 if (!flushGLStateCommon(type)) {
1325 return false;
1326 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001327
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001328 if (fDirtyFlags.fRenderTargetChanged) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001329 // our coords are in pixel space and the GL matrices map to NDC
1330 // so if the viewport changed, our matrix is now wrong.
bsalomon@google.com4be283f2011-04-19 21:15:09 +00001331#if GR_GL_ATTRIBUTE_MATRICES
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001332 fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
reed@google.comac10a2d2010-12-22 21:39:39 +00001333#else
1334 // we assume all shader matrices may be wrong after viewport changes
1335 fProgramCache->invalidateViewMatrices();
1336#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001337 }
1338
bsalomon@google.com4be283f2011-04-19 21:15:09 +00001339 ProgramDesc desc;
1340 flushProgram(type, &desc);
reed@google.comac10a2d2010-12-22 21:39:39 +00001341
bsalomon@google.com4be283f2011-04-19 21:15:09 +00001342 flushColor(desc);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001343
bsalomon@google.com4be283f2011-04-19 21:15:09 +00001344#if GR_GL_ATTRIBUTE_MATRICES
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001345 GrMatrix& currViewMatrix = fHWDrawState.fViewMatrix;
reed@google.comac10a2d2010-12-22 21:39:39 +00001346#else
1347 GrMatrix& currViewMatrix = fProgram->fViewMatrix;
reed@google.comac10a2d2010-12-22 21:39:39 +00001348#endif
1349
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001350 if (currViewMatrix != fCurrDrawState.fViewMatrix) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001351 flushViewMatrix();
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001352 currViewMatrix = fCurrDrawState.fViewMatrix;
reed@google.comac10a2d2010-12-22 21:39:39 +00001353 }
1354
bsalomon@google.com316f99232011-01-13 21:28:12 +00001355 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001356 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
1357 if (NULL != texture) {
1358 if (-1 != fProgram->fUniLocations.fStages[s].fTextureMatrixUni &&
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001359 (((1 << s) & fDirtyFlags.fTextureChangedMask) ||
1360 getHWSamplerMatrix(s) != getSamplerMatrix(s))) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001361 flushTextureMatrix(s);
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001362 recordHWSamplerMatrix(s, getSamplerMatrix(s));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001363 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001364 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001365
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001366 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
1367 if (-1 != fProgram->fUniLocations.fStages[s].fRadial2Uni &&
1368 (fProgram->fRadial2CenterX1[s] != sampler.getRadial2CenterX1() ||
1369 fProgram->fRadial2Radius0[s] != sampler.getRadial2Radius0() ||
1370 fProgram->fRadial2PosRoot[s] != sampler.isRadial2PosRoot())) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001371
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001372 flushRadial2(s);
reed@google.comac10a2d2010-12-22 21:39:39 +00001373
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001374 fProgram->fRadial2CenterX1[s] = sampler.getRadial2CenterX1();
1375 fProgram->fRadial2Radius0[s] = sampler.getRadial2Radius0();
1376 fProgram->fRadial2PosRoot[s] = sampler.isRadial2PosRoot();
1377 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001378 }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001379 resetDirtyFlags();
reed@google.comac10a2d2010-12-22 21:39:39 +00001380 return true;
1381}
1382
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001383void GrGpuGLShaders2::setupGeometry(int* startVertex,
1384 int* startIndex,
1385 int vertexCount,
1386 int indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001387
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001388 int newColorOffset;
1389 int newTexCoordOffsets[kMaxTexCoords];
reed@google.comac10a2d2010-12-22 21:39:39 +00001390
twiz@google.com0f31ca72011-03-18 17:38:11 +00001391 GrGLsizei newStride = VertexSizeAndOffsetsByIdx(fGeometrySrc.fVertexLayout,
1392 newTexCoordOffsets,
1393 &newColorOffset);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001394 int oldColorOffset;
1395 int oldTexCoordOffsets[kMaxTexCoords];
twiz@google.com0f31ca72011-03-18 17:38:11 +00001396 GrGLsizei oldStride = VertexSizeAndOffsetsByIdx(fHWGeometryState.fVertexLayout,
1397 oldTexCoordOffsets,
1398 &oldColorOffset);
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001399 bool indexed = NULL != startIndex;
reed@google.comac10a2d2010-12-22 21:39:39 +00001400
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001401 int extraVertexOffset;
1402 int extraIndexOffset;
1403 setBuffers(indexed, &extraVertexOffset, &extraIndexOffset);
reed@google.comac10a2d2010-12-22 21:39:39 +00001404
twiz@google.com0f31ca72011-03-18 17:38:11 +00001405 GrGLenum scalarType;
reed@google.comac10a2d2010-12-22 21:39:39 +00001406 bool texCoordNorm;
1407 if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) {
1408 scalarType = GrGLTextType;
1409 texCoordNorm = GR_GL_TEXT_TEXTURE_NORMALIZED;
1410 } else {
1411 scalarType = GrGLType;
1412 texCoordNorm = false;
1413 }
1414
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001415 size_t vertexOffset = (*startVertex + extraVertexOffset) * newStride;
1416 *startVertex = 0;
1417 if (indexed) {
1418 *startIndex += extraIndexOffset;
1419 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001420
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001421 // all the Pointers must be set if any of these are true
1422 bool allOffsetsChange = fHWGeometryState.fArrayPtrsDirty ||
1423 vertexOffset != fHWGeometryState.fVertexOffset ||
1424 newStride != oldStride;
1425
1426 // position and tex coord offsets change if above conditions are true
1427 // or the type/normalization changed based on text vs nontext type coords.
1428 bool posAndTexChange = allOffsetsChange ||
1429 (((GrGLTextType != GrGLType) || GR_GL_TEXT_TEXTURE_NORMALIZED) &&
1430 (kTextFormat_VertexLayoutBit &
1431 (fHWGeometryState.fVertexLayout ^
1432 fGeometrySrc.fVertexLayout)));
1433
1434 if (posAndTexChange) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001435 GR_GL(VertexAttribPointer(POS_ATTR_LOCATION, 2, scalarType,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001436 false, newStride, (GrGLvoid*)vertexOffset));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001437 fHWGeometryState.fVertexOffset = vertexOffset;
reed@google.comac10a2d2010-12-22 21:39:39 +00001438 }
1439
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001440 for (int t = 0; t < kMaxTexCoords; ++t) {
1441 if (newTexCoordOffsets[t] > 0) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001442 GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffsets[t]);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001443 if (oldTexCoordOffsets[t] <= 0) {
1444 GR_GL(EnableVertexAttribArray(TEX_ATTR_LOCATION(t)));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001445 GR_GL(VertexAttribPointer(TEX_ATTR_LOCATION(t), 2, scalarType,
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001446 texCoordNorm, newStride, texCoordOffset));
1447 } else if (posAndTexChange ||
1448 newTexCoordOffsets[t] != oldTexCoordOffsets[t]) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001449 GR_GL(VertexAttribPointer(TEX_ATTR_LOCATION(t), 2, scalarType,
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001450 texCoordNorm, newStride, texCoordOffset));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001451 }
1452 } else if (oldTexCoordOffsets[t] > 0) {
1453 GR_GL(DisableVertexAttribArray(TEX_ATTR_LOCATION(t)));
reed@google.comac10a2d2010-12-22 21:39:39 +00001454 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001455 }
1456
1457 if (newColorOffset > 0) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001458 GrGLvoid* colorOffset = (int8_t*)(vertexOffset + newColorOffset);
reed@google.comac10a2d2010-12-22 21:39:39 +00001459 if (oldColorOffset <= 0) {
1460 GR_GL(EnableVertexAttribArray(COL_ATTR_LOCATION));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001461 GR_GL(VertexAttribPointer(COL_ATTR_LOCATION, 4,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001462 GR_GL_UNSIGNED_BYTE,
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001463 true, newStride, colorOffset));
1464 } else if (allOffsetsChange || newColorOffset != oldColorOffset) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001465 GR_GL(VertexAttribPointer(COL_ATTR_LOCATION, 4,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001466 GR_GL_UNSIGNED_BYTE,
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001467 true, newStride, colorOffset));
reed@google.comac10a2d2010-12-22 21:39:39 +00001468 }
1469 } else if (oldColorOffset > 0) {
1470 GR_GL(DisableVertexAttribArray(COL_ATTR_LOCATION));
1471 }
1472
1473 fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001474 fHWGeometryState.fArrayPtrsDirty = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001475}