blob: 94b941fc0923835bfb08d6e0a18891d6db303f45 [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) {
253 return (x & 0x00ff00) | (x << 24) | (x >> 24);
254}
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 {
1041 desc->fColorType = ProgramDesc::kAttribute_ColorType;
1042 }
bsalomon@google.comd16983b2011-02-02 22:42:20 +00001043
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001044 for (int s = 0; s < kNumStages; ++s) {
1045 StageDesc& stage = desc->fStages[s];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001046
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001047 stage.fEnabled = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
reed@google.comac10a2d2010-12-22 21:39:39 +00001048
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001049 if (stage.fEnabled) {
1050 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
1051 GrAssert(NULL != texture);
1052 // we matrix to invert when orientation is TopDown, so make sure
1053 // we aren't in that case before flagging as identity.
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001054 if (TextureMatrixIsIdentity(texture, fCurrDrawState.fSamplerStates[s])) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001055 stage.fOptFlags = StageDesc::kIdentityMatrix_OptFlagBit;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001056 } else if (!getSamplerMatrix(s).hasPerspective()) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001057 stage.fOptFlags = StageDesc::kNoPerspective_OptFlagBit;
1058 } else {
1059 stage.fOptFlags = 0;
1060 }
1061 switch (fCurrDrawState.fSamplerStates[s].getSampleMode()) {
1062 case GrSamplerState::kNormal_SampleMode:
1063 stage.fCoordMapping = StageDesc::kIdentity_CoordMapping;
1064 break;
1065 case GrSamplerState::kRadial_SampleMode:
1066 stage.fCoordMapping = StageDesc::kRadialGradient_CoordMapping;
1067 break;
1068 case GrSamplerState::kRadial2_SampleMode:
1069 stage.fCoordMapping = StageDesc::kRadial2Gradient_CoordMapping;
1070 break;
1071 case GrSamplerState::kSweep_SampleMode:
1072 stage.fCoordMapping = StageDesc::kSweepGradient_CoordMapping;
1073 break;
1074 default:
1075 GrAssert(!"Unexpected sample mode!");
1076 break;
1077 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001078 if (GrPixelConfigIsAlphaOnly(texture->config())) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001079 stage.fModulation = StageDesc::kAlpha_Modulation;
1080 } else {
1081 stage.fModulation = StageDesc::kColor_Modulation;
1082 }
1083 } else {
1084 stage.fOptFlags = 0;
1085 stage.fCoordMapping = (StageDesc::CoordMapping)0;
1086 stage.fModulation = (StageDesc::Modulation)0;
1087 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001088 }
1089}
1090
twiz@google.com0f31ca72011-03-18 17:38:11 +00001091GrGLuint GrGpuGLShaders2::CompileShader(GrGLenum type,
1092 int stringCnt,
1093 const char** strings,
1094 int* stringLengths) {
1095 GrGLuint shader = GR_GL(CreateShader(type));
reed@google.comac10a2d2010-12-22 21:39:39 +00001096 if (0 == shader) {
1097 return 0;
1098 }
1099
twiz@google.com0f31ca72011-03-18 17:38:11 +00001100 GrGLint compiled = GR_GL_INIT_ZERO;
reed@google.comac10a2d2010-12-22 21:39:39 +00001101 GR_GL(ShaderSource(shader, stringCnt, strings, stringLengths));
1102 GR_GL(CompileShader(shader));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001103 GR_GL(GetShaderiv(shader, GR_GL_COMPILE_STATUS, &compiled));
reed@google.comac10a2d2010-12-22 21:39:39 +00001104
1105 if (!compiled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001106 GrGLint infoLen = GR_GL_INIT_ZERO;
1107 GR_GL(GetShaderiv(shader, GR_GL_INFO_LOG_LENGTH, &infoLen));
reed@google.comac10a2d2010-12-22 21:39:39 +00001108 GrAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
1109 if (infoLen > 0) {
1110 GR_GL(GetShaderInfoLog(shader, infoLen+1, NULL, (char*)log.get()));
1111 for (int i = 0; i < stringCnt; ++i) {
1112 if (NULL == stringLengths || stringLengths[i] < 0) {
1113 GrPrintf(strings[i]);
1114 } else {
1115 GrPrintf("%.*s", stringLengths[i], strings[i]);
1116 }
1117 }
1118 GrPrintf("\n%s", log.get());
1119 }
1120 GrAssert(!"Shader compilation failed!");
1121 GR_GL(DeleteShader(shader));
1122 return 0;
1123 }
1124 return shader;
1125}
1126
1127void GrGpuGLShaders2::DeleteProgram(Program* program) {
1128 GR_GL(DeleteShader(program->fVShaderID));
1129 GR_GL(DeleteShader(program->fFShaderID));
1130 GR_GL(DeleteProgram(program->fProgramID));
1131 GR_DEBUGCODE(memset(program, 0, sizeof(Program)));
1132}
1133
1134
1135GrGpuGLShaders2::GrGpuGLShaders2() {
1136
reed@google.comac10a2d2010-12-22 21:39:39 +00001137 fProgram = NULL;
1138 fProgramCache = new ProgramCache();
1139
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001140#if 0
reed@google.comac10a2d2010-12-22 21:39:39 +00001141 ProgramUnitTest();
1142#endif
1143}
1144
1145GrGpuGLShaders2::~GrGpuGLShaders2() {
1146 delete fProgramCache;
1147}
1148
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001149const GrMatrix& GrGpuGLShaders2::getHWSamplerMatrix(int stage) {
bsalomon@google.com4be283f2011-04-19 21:15:09 +00001150#if GR_GL_ATTRIBUTE_MATRICES
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001151 return fHWDrawState.fSamplerStates[stage].getMatrix();
1152#else
1153 return fProgram->fTextureMatrices[stage];
1154#endif
1155}
1156
1157void GrGpuGLShaders2::recordHWSamplerMatrix(int stage, const GrMatrix& matrix){
bsalomon@google.com4be283f2011-04-19 21:15:09 +00001158#if GR_GL_ATTRIBUTE_MATRICES
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001159 fHWDrawState.fSamplerStates[stage].setMatrix(matrix);
1160#else
1161 fProgram->fTextureMatrices[stage] = matrix;
1162#endif
1163}
1164
reed@google.comac10a2d2010-12-22 21:39:39 +00001165void GrGpuGLShaders2::resetContext() {
reed@google.comac10a2d2010-12-22 21:39:39 +00001166
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001167 INHERITED::resetContext();
1168
reed@google.comac10a2d2010-12-22 21:39:39 +00001169 fHWGeometryState.fVertexLayout = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001170 fHWGeometryState.fVertexOffset = ~0;
reed@google.comac10a2d2010-12-22 21:39:39 +00001171 GR_GL(DisableVertexAttribArray(COL_ATTR_LOCATION));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001172 for (int t = 0; t < kMaxTexCoords; ++t) {
1173 GR_GL(DisableVertexAttribArray(TEX_ATTR_LOCATION(t)));
1174 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001175 GR_GL(EnableVertexAttribArray(POS_ATTR_LOCATION));
1176
1177 fHWProgramID = 0;
1178}
1179
1180void GrGpuGLShaders2::flushViewMatrix() {
1181 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1182 GrMatrix m (
1183 GrIntToScalar(2) / fCurrDrawState.fRenderTarget->width(), 0, -GR_Scalar1,
1184 0,-GrIntToScalar(2) / fCurrDrawState.fRenderTarget->height(), GR_Scalar1,
1185 0, 0, GrMatrix::I()[8]);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001186 m.setConcat(m, fCurrDrawState.fViewMatrix);
reed@google.comac10a2d2010-12-22 21:39:39 +00001187
1188 // ES doesn't allow you to pass true to the transpose param,
1189 // so do our own transpose
1190 GrScalar mt[] = {
1191 m[GrMatrix::kScaleX],
1192 m[GrMatrix::kSkewY],
1193 m[GrMatrix::kPersp0],
1194 m[GrMatrix::kSkewX],
1195 m[GrMatrix::kScaleY],
1196 m[GrMatrix::kPersp1],
1197 m[GrMatrix::kTransX],
1198 m[GrMatrix::kTransY],
1199 m[GrMatrix::kPersp2]
1200 };
bsalomon@google.com4be283f2011-04-19 21:15:09 +00001201#if GR_GL_ATTRIBUTE_MATRICES
bsalomon@google.com316f99232011-01-13 21:28:12 +00001202 GR_GL(VertexAttrib4fv(VIEWMAT_ATTR_LOCATION+0, mt+0));
1203 GR_GL(VertexAttrib4fv(VIEWMAT_ATTR_LOCATION+1, mt+3));
1204 GR_GL(VertexAttrib4fv(VIEWMAT_ATTR_LOCATION+2, mt+6));
reed@google.comac10a2d2010-12-22 21:39:39 +00001205#else
1206 GR_GL(UniformMatrix3fv(fProgram->fUniLocations.fViewMatrixUni,1,false,mt));
1207#endif
1208}
1209
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001210void GrGpuGLShaders2::flushTextureMatrix(int stage) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001211 GrAssert(NULL != fCurrDrawState.fTextures[stage]);
reed@google.comac10a2d2010-12-22 21:39:39 +00001212
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001213 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[stage];
1214
1215 GrMatrix m = getSamplerMatrix(stage);
1216 GrSamplerState::SampleMode mode =
1217 fCurrDrawState.fSamplerStates[0].getSampleMode();
1218 AdjustTextureMatrix(texture, mode, &m);
reed@google.comac10a2d2010-12-22 21:39:39 +00001219
1220 // ES doesn't allow you to pass true to the transpose param,
1221 // so do our own transpose
1222 GrScalar mt[] = {
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001223 m[GrMatrix::kScaleX],
1224 m[GrMatrix::kSkewY],
1225 m[GrMatrix::kPersp0],
1226 m[GrMatrix::kSkewX],
1227 m[GrMatrix::kScaleY],
1228 m[GrMatrix::kPersp1],
1229 m[GrMatrix::kTransX],
1230 m[GrMatrix::kTransY],
1231 m[GrMatrix::kPersp2]
reed@google.comac10a2d2010-12-22 21:39:39 +00001232 };
bsalomon@google.com4be283f2011-04-19 21:15:09 +00001233#if GR_GL_ATTRIBUTE_MATRICES
bsalomon@google.com316f99232011-01-13 21:28:12 +00001234 GR_GL(VertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+0, mt+0));
1235 GR_GL(VertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+1, mt+3));
1236 GR_GL(VertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+2, mt+6));
reed@google.comac10a2d2010-12-22 21:39:39 +00001237#else
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001238 GR_GL(UniformMatrix3fv(fProgram->fUniLocations.fStages[stage].fTextureMatrixUni,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001239 1, false, mt));
reed@google.comac10a2d2010-12-22 21:39:39 +00001240#endif
1241}
1242
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001243void GrGpuGLShaders2::flushRadial2(int stage) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001244
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001245 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[stage];
reed@google.comac10a2d2010-12-22 21:39:39 +00001246
1247 GrScalar centerX1 = sampler.getRadial2CenterX1();
1248 GrScalar radius0 = sampler.getRadial2Radius0();
1249
1250 GrScalar a = GrMul(centerX1, centerX1) - GR_Scalar1;
1251
1252 float unis[6] = {
1253 GrScalarToFloat(a),
1254 1 / (2.f * unis[0]),
1255 GrScalarToFloat(centerX1),
1256 GrScalarToFloat(radius0),
1257 GrScalarToFloat(GrMul(radius0, radius0)),
1258 sampler.isRadial2PosRoot() ? 1.f : -1.f
1259 };
bsalomon@google.com316f99232011-01-13 21:28:12 +00001260 GR_GL(Uniform1fv(fProgram->fUniLocations.fStages[stage].fRadial2Uni,
1261 6,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001262 unis));
reed@google.comac10a2d2010-12-22 21:39:39 +00001263}
1264
bsalomon@google.com4be283f2011-04-19 21:15:09 +00001265void GrGpuGLShaders2::flushProgram(GrPrimitiveType type, ProgramDesc* desc) {
1266 getProgramDesc(type, desc);
1267 fProgram = fProgramCache->getProgram(*desc);
reed@google.comac10a2d2010-12-22 21:39:39 +00001268
1269 if (fHWProgramID != fProgram->fProgramID) {
1270 GR_GL(UseProgram(fProgram->fProgramID));
1271 fHWProgramID = fProgram->fProgramID;
1272#if GR_COLLECT_STATS
1273 ++fStats.fProgChngCnt;
1274#endif
1275 }
1276}
1277
bsalomon@google.com4be283f2011-04-19 21:15:09 +00001278void GrGpuGLShaders2::flushColor(const ProgramDesc& desc) {
1279 if (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) {
1280 // color will be specified per-vertex as an attribute
1281 // invalidate the const vertex attrib color
1282 fHWDrawState.fColor = GrColor_ILLEGAL;
1283 } else {
1284 switch (desc.fColorType) {
1285 case ProgramDesc::kAttribute_ColorType:
1286 if (fHWDrawState.fColor != fCurrDrawState.fColor) {
1287 // OpenGL ES only supports the float varities of glVertexAttrib
1288 float c[] = {
1289 GrColorUnpackR(fCurrDrawState.fColor) / 255.f,
1290 GrColorUnpackG(fCurrDrawState.fColor) / 255.f,
1291 GrColorUnpackB(fCurrDrawState.fColor) / 255.f,
1292 GrColorUnpackA(fCurrDrawState.fColor) / 255.f
1293 };
1294 GR_GL(VertexAttrib4fv(COL_ATTR_LOCATION, c));
1295 fHWDrawState.fColor = fCurrDrawState.fColor;
1296 }
1297 break;
1298 case ProgramDesc::kUniform_ColorType:
1299 if (fProgram->fColor != fCurrDrawState.fColor) {
1300 // OpenGL ES only supports the float varities of glVertexAttrib
1301 float c[] = {
1302 GrColorUnpackR(fCurrDrawState.fColor) / 255.f,
1303 GrColorUnpackG(fCurrDrawState.fColor) / 255.f,
1304 GrColorUnpackB(fCurrDrawState.fColor) / 255.f,
1305 GrColorUnpackA(fCurrDrawState.fColor) / 255.f
1306 };
1307 GrAssert(-1 != fProgram->fUniLocations.fColorUni);
1308 GR_GL(Uniform4fv(fProgram->fUniLocations.fColorUni, 1, c));
1309 fProgram->fColor = fCurrDrawState.fColor;
1310 }
1311 break;
1312 case ProgramDesc::kNone_ColorType:
1313 GrAssert(0xffffffff == fCurrDrawState.fColor);
1314 break;
1315 default:
1316 GrCrash("Unknown color type.");
1317 }
1318 }
1319}
1320
bsalomon@google.comffca4002011-02-22 20:34:01 +00001321bool GrGpuGLShaders2::flushGraphicsState(GrPrimitiveType type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001322
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001323 if (!flushGLStateCommon(type)) {
1324 return false;
1325 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001326
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001327 if (fDirtyFlags.fRenderTargetChanged) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001328 // our coords are in pixel space and the GL matrices map to NDC
1329 // so if the viewport changed, our matrix is now wrong.
bsalomon@google.com4be283f2011-04-19 21:15:09 +00001330#if GR_GL_ATTRIBUTE_MATRICES
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001331 fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
reed@google.comac10a2d2010-12-22 21:39:39 +00001332#else
1333 // we assume all shader matrices may be wrong after viewport changes
1334 fProgramCache->invalidateViewMatrices();
1335#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001336 }
1337
bsalomon@google.com4be283f2011-04-19 21:15:09 +00001338 ProgramDesc desc;
1339 flushProgram(type, &desc);
reed@google.comac10a2d2010-12-22 21:39:39 +00001340
bsalomon@google.com4be283f2011-04-19 21:15:09 +00001341 flushColor(desc);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001342
bsalomon@google.com4be283f2011-04-19 21:15:09 +00001343#if GR_GL_ATTRIBUTE_MATRICES
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001344 GrMatrix& currViewMatrix = fHWDrawState.fViewMatrix;
reed@google.comac10a2d2010-12-22 21:39:39 +00001345#else
1346 GrMatrix& currViewMatrix = fProgram->fViewMatrix;
reed@google.comac10a2d2010-12-22 21:39:39 +00001347#endif
1348
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001349 if (currViewMatrix != fCurrDrawState.fViewMatrix) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001350 flushViewMatrix();
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001351 currViewMatrix = fCurrDrawState.fViewMatrix;
reed@google.comac10a2d2010-12-22 21:39:39 +00001352 }
1353
bsalomon@google.com316f99232011-01-13 21:28:12 +00001354 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001355 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
1356 if (NULL != texture) {
1357 if (-1 != fProgram->fUniLocations.fStages[s].fTextureMatrixUni &&
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001358 (((1 << s) & fDirtyFlags.fTextureChangedMask) ||
1359 getHWSamplerMatrix(s) != getSamplerMatrix(s))) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001360 flushTextureMatrix(s);
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001361 recordHWSamplerMatrix(s, getSamplerMatrix(s));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001362 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001363 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001364
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001365 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
1366 if (-1 != fProgram->fUniLocations.fStages[s].fRadial2Uni &&
1367 (fProgram->fRadial2CenterX1[s] != sampler.getRadial2CenterX1() ||
1368 fProgram->fRadial2Radius0[s] != sampler.getRadial2Radius0() ||
1369 fProgram->fRadial2PosRoot[s] != sampler.isRadial2PosRoot())) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001370
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001371 flushRadial2(s);
reed@google.comac10a2d2010-12-22 21:39:39 +00001372
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001373 fProgram->fRadial2CenterX1[s] = sampler.getRadial2CenterX1();
1374 fProgram->fRadial2Radius0[s] = sampler.getRadial2Radius0();
1375 fProgram->fRadial2PosRoot[s] = sampler.isRadial2PosRoot();
1376 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001377 }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001378 resetDirtyFlags();
reed@google.comac10a2d2010-12-22 21:39:39 +00001379 return true;
1380}
1381
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001382void GrGpuGLShaders2::setupGeometry(int* startVertex,
1383 int* startIndex,
1384 int vertexCount,
1385 int indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001386
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001387 int newColorOffset;
1388 int newTexCoordOffsets[kMaxTexCoords];
reed@google.comac10a2d2010-12-22 21:39:39 +00001389
twiz@google.com0f31ca72011-03-18 17:38:11 +00001390 GrGLsizei newStride = VertexSizeAndOffsetsByIdx(fGeometrySrc.fVertexLayout,
1391 newTexCoordOffsets,
1392 &newColorOffset);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001393 int oldColorOffset;
1394 int oldTexCoordOffsets[kMaxTexCoords];
twiz@google.com0f31ca72011-03-18 17:38:11 +00001395 GrGLsizei oldStride = VertexSizeAndOffsetsByIdx(fHWGeometryState.fVertexLayout,
1396 oldTexCoordOffsets,
1397 &oldColorOffset);
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001398 bool indexed = NULL != startIndex;
reed@google.comac10a2d2010-12-22 21:39:39 +00001399
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001400 int extraVertexOffset;
1401 int extraIndexOffset;
1402 setBuffers(indexed, &extraVertexOffset, &extraIndexOffset);
reed@google.comac10a2d2010-12-22 21:39:39 +00001403
twiz@google.com0f31ca72011-03-18 17:38:11 +00001404 GrGLenum scalarType;
reed@google.comac10a2d2010-12-22 21:39:39 +00001405 bool texCoordNorm;
1406 if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) {
1407 scalarType = GrGLTextType;
1408 texCoordNorm = GR_GL_TEXT_TEXTURE_NORMALIZED;
1409 } else {
1410 scalarType = GrGLType;
1411 texCoordNorm = false;
1412 }
1413
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001414 size_t vertexOffset = (*startVertex + extraVertexOffset) * newStride;
1415 *startVertex = 0;
1416 if (indexed) {
1417 *startIndex += extraIndexOffset;
1418 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001419
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001420 // all the Pointers must be set if any of these are true
1421 bool allOffsetsChange = fHWGeometryState.fArrayPtrsDirty ||
1422 vertexOffset != fHWGeometryState.fVertexOffset ||
1423 newStride != oldStride;
1424
1425 // position and tex coord offsets change if above conditions are true
1426 // or the type/normalization changed based on text vs nontext type coords.
1427 bool posAndTexChange = allOffsetsChange ||
1428 (((GrGLTextType != GrGLType) || GR_GL_TEXT_TEXTURE_NORMALIZED) &&
1429 (kTextFormat_VertexLayoutBit &
1430 (fHWGeometryState.fVertexLayout ^
1431 fGeometrySrc.fVertexLayout)));
1432
1433 if (posAndTexChange) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001434 GR_GL(VertexAttribPointer(POS_ATTR_LOCATION, 2, scalarType,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001435 false, newStride, (GrGLvoid*)vertexOffset));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001436 fHWGeometryState.fVertexOffset = vertexOffset;
reed@google.comac10a2d2010-12-22 21:39:39 +00001437 }
1438
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001439 for (int t = 0; t < kMaxTexCoords; ++t) {
1440 if (newTexCoordOffsets[t] > 0) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001441 GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffsets[t]);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001442 if (oldTexCoordOffsets[t] <= 0) {
1443 GR_GL(EnableVertexAttribArray(TEX_ATTR_LOCATION(t)));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001444 GR_GL(VertexAttribPointer(TEX_ATTR_LOCATION(t), 2, scalarType,
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001445 texCoordNorm, newStride, texCoordOffset));
1446 } else if (posAndTexChange ||
1447 newTexCoordOffsets[t] != oldTexCoordOffsets[t]) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001448 GR_GL(VertexAttribPointer(TEX_ATTR_LOCATION(t), 2, scalarType,
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001449 texCoordNorm, newStride, texCoordOffset));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001450 }
1451 } else if (oldTexCoordOffsets[t] > 0) {
1452 GR_GL(DisableVertexAttribArray(TEX_ATTR_LOCATION(t)));
reed@google.comac10a2d2010-12-22 21:39:39 +00001453 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001454 }
1455
1456 if (newColorOffset > 0) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001457 GrGLvoid* colorOffset = (int8_t*)(vertexOffset + newColorOffset);
reed@google.comac10a2d2010-12-22 21:39:39 +00001458 if (oldColorOffset <= 0) {
1459 GR_GL(EnableVertexAttribArray(COL_ATTR_LOCATION));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001460 GR_GL(VertexAttribPointer(COL_ATTR_LOCATION, 4,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001461 GR_GL_UNSIGNED_BYTE,
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001462 true, newStride, colorOffset));
1463 } else if (allOffsetsChange || newColorOffset != oldColorOffset) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001464 GR_GL(VertexAttribPointer(COL_ATTR_LOCATION, 4,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001465 GR_GL_UNSIGNED_BYTE,
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001466 true, newStride, colorOffset));
reed@google.comac10a2d2010-12-22 21:39:39 +00001467 }
1468 } else if (oldColorOffset > 0) {
1469 GR_GL(DisableVertexAttribArray(COL_ATTR_LOCATION));
1470 }
1471
1472 fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001473 fHWGeometryState.fArrayPtrsDirty = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001474}