blob: 0a15be1c40db986e7acf2fbb3c5a05e8cc0fd5b5 [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
2 Copyright 2010 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17
18#include "GrGLConfig.h"
19
20#if GR_SUPPORT_GLES2 || GR_SUPPORT_GLDESKTOP
21
22#include "GrGpuGLShaders2.h"
23#include "GrGpuVertex.h"
24#include "GrMemory.h"
25#include "GrStringBuilder.h"
26
27
28#define ATTRIBUTE_MATRIX 0
29
30#define SKIP_COLOR_MODULATE_OPT 0
31
32#define PRINT_SHADERS 0
33
34#define SKIP_CACHE_CHECK true
35
36#if GR_SUPPORT_GLES2
37 #define GR_PRECISION "mediump"
38 const char GR_SHADER_PRECISION[] = "precision mediump float;\n";
39#else
40 #define GR_PRECISION ""
41 const char GR_SHADER_PRECISION[] = "";
42#endif
43
44#define POS_ATTR_LOCATION 0
45#define TEX_ATTR_LOCATION 1
46#define COL_ATTR_LOCATION 2
47#if ATTRIBUTE_MATRIX
48#define VIEWMAT_ATTR_LOCATION 3
49#define TEXMAT_ATTR_LOCATION(X) (6 + 3 * (X))
50#define BOGUS_MATRIX_UNI_LOCATION 1000
51#endif
52
53const int GrGpuGLShaders2::NUM_STAGES = 1;
54
55struct GrGpuGLShaders2::StageUniLocations {
56 GLint fTextureMatrixUni;
57 GLint fSamplerUni;
58 GLint fRadial2Uni;
59};
60
61struct GrGpuGLShaders2::UniLocations {
62 GLint fViewMatrixUni;
63 StageUniLocations fStages[NUM_STAGES];
64};
65
66// Records per-program information
67// we can specify the attribute locations so that they are constant
68// across our shaders. But the driver determines the uniform locations
69// at link time. We don't need to remember the sampler uniform location
70// because we will bind a texture slot to it and never change it
71// Uniforms are program-local so we can't rely on fHWState to hold the
72// previous uniform state after a program change.
73struct GrGpuGLShaders2::Program {
74 // IDs
75 GLuint fVShaderID;
76 GLuint fFShaderID;
77 GLuint fProgramID;
78
79 // shader uniform locations (-1 if shader doesn't use them)
80 UniLocations fUniLocations;
81
82 // these reflect the current values of uniforms
83 // (GL uniform values travel with program)
84 GrMatrix fViewMatrix;
85 GrMatrix fTextureMatrix[NUM_STAGES];
86 GrGLTexture::Orientation fTextureOrientation[NUM_STAGES];
87 GrScalar fRadial2CenterX1[NUM_STAGES];
88 GrScalar fRadial2Radius0[NUM_STAGES];
89 bool fRadial2PosRoot[NUM_STAGES];
90
91};
92
93// must be tightly packed
94struct GrGpuGLShaders2::StageDesc {
95 enum OptFlagBits {
96 kNoPerspective_OptFlagBit = 0x1,
97 kIdentityMatrix_OptFlagBit = 0x2,
98 };
99 int fOptFlags : 8;
100 bool fEnabled;
101 enum Modulation {
102 kColor_Modulation,
103 kAlpha_Modulation,
104 } fModulation : 8;
105 enum CoordMapping {
106 kIdentity_CoordMapping,
107 kRadialGradient_CoordMapping,
108 kSweepGradient_CoordMapping,
109 kRadial2Gradient_CoordMapping,
110 } fCoordMapping : 8;
111};
112
113// must be tightly packed
114struct GrGpuGLShaders2::ProgramDesc {
115 GrVertexLayout fVertexLayout;
116 enum {
117 kNotPoints_OptFlagBit = 0x1,
118 kVertexColorAllOnes_OptFlagBit = 0x2,
119 };
120 // we're assuming optflags and layout pack into 32 bits
121 GR_STATIC_ASSERT(2 == sizeof(GrVertexLayout));
122 int fOptFlags : 16;
123
124 StageDesc fStages[NUM_STAGES];
125
126 bool operator == (const ProgramDesc& desc) const {
127 // keep 4-byte aligned and tightly packed
128 GR_STATIC_ASSERT(4 == sizeof(StageDesc));
129 GR_STATIC_ASSERT(2 + 2 + 4 * NUM_STAGES == sizeof(ProgramDesc));
130 return 0 == memcmp(this, &desc, sizeof(ProgramDesc));
131 }
132};
133
134#include "GrTHashCache.h"
135
136class GrGpuGLShaders2::ProgramCache : public ::GrNoncopyable {
137private:
138 struct Entry;
139 class HashKey {
140 public:
141 HashKey();
142 HashKey(const ProgramDesc& desc);
143 static const HashKey& GetKey(const Entry&);
144 static bool EQ(const Entry&, const HashKey&);
145 static bool LT(const Entry&, const HashKey&);
146 bool operator <(const HashKey& key) const;
147 bool operator ==(const HashKey& key) const;
148 uint32_t getHash() const;
149 private:
150 ProgramDesc fDesc;
151 uint32_t fHash;
152 };
153
154 struct Entry {
155 Program fProgram;
156 HashKey fKey;
157 uint32_t fLRUStamp;
158 };
159
160 // if hash bits is changed, need to change hash function
161 GrTHashTable<Entry, HashKey, 8> fHashCache;
162
163 static const int MAX_ENTRIES = 16;
164 Entry fEntries[MAX_ENTRIES];
165 int fCount;
166 uint32_t fCurrLRUStamp;
167
168public:
169 ProgramCache() {
170 fCount = 0;
171 fCurrLRUStamp = 0;
172 }
173
174 ~ProgramCache() {
175 for (int i = 0; i < fCount; ++i) {
176 GrGpuGLShaders2::DeleteProgram(&fEntries[i].fProgram);
177 }
178 }
179
180 void abandon() {
181 fCount = 0;
182 }
183
184 void invalidateViewMatrices() {
185 for (int i = 0; i < fCount; ++i) {
186 // set to illegal matrix
187 fEntries[i].fProgram.fViewMatrix.setScale(GR_ScalarMax,
188 GR_ScalarMax);
189 }
190 }
191
192 Program* getProgram(const ProgramDesc& desc) {
193 HashKey key(desc);
194 Entry* entry = fHashCache.find(key);
195 if (NULL == entry) {
196 if (fCount < MAX_ENTRIES) {
197 entry = fEntries + fCount;
198 ++fCount;
199 } else {
200 GrAssert(MAX_ENTRIES == fCount);
201 entry = fEntries;
202 for (int i = 1; i < MAX_ENTRIES; ++i) {
203 if (fEntries[i].fLRUStamp < entry->fLRUStamp) {
204 entry = fEntries + i;
205 }
206 }
207 fHashCache.remove(entry->fKey, entry);
208 GrGpuGLShaders2::DeleteProgram(&entry->fProgram);
209 }
210 entry->fKey = key;
211 GrGpuGLShaders2::GenProgram(desc, &entry->fProgram);
212 fHashCache.insert(entry->fKey, entry);
213 }
214
215 entry->fLRUStamp = fCurrLRUStamp;
216 if (UINT32_MAX == fCurrLRUStamp) {
217 // wrap around! just trash our LRU, one time hit.
218 for (int i = 0; i < fCount; ++i) {
219 fEntries[i].fLRUStamp = 0;
220 }
221 }
222 ++fCurrLRUStamp;
223 return &entry->fProgram;
224 }
225};
226
227GrGpuGLShaders2::ProgramCache::HashKey::HashKey() {
228}
229
230static uint32_t ror(uint32_t x) {
231 return (x >> 8) | (x << 24);
232}
233
234
235GrGpuGLShaders2::ProgramCache::HashKey::HashKey(const ProgramDesc& desc) {
236 fDesc = desc;
237 // if you change the size of the desc, need to update the hash function
238 GR_STATIC_ASSERT(8 == sizeof(ProgramDesc));
239
240 uint32_t* d = (uint32_t*) &fDesc;
241 fHash = d[0] ^ ror(d[1]);
242}
243
244bool GrGpuGLShaders2::ProgramCache::HashKey::EQ(const Entry& entry,
245 const HashKey& key) {
246 return entry.fKey == key;
247}
248
249bool GrGpuGLShaders2::ProgramCache::HashKey::LT(const Entry& entry,
250 const HashKey& key) {
251 return entry.fKey < key;
252}
253
254bool GrGpuGLShaders2::ProgramCache::HashKey::operator ==(const HashKey& key) const {
255 return fDesc == key.fDesc;
256}
257
258bool GrGpuGLShaders2::ProgramCache::HashKey::operator <(const HashKey& key) const {
259 return memcmp(&fDesc, &key.fDesc, sizeof(HashKey)) < 0;
260}
261
262uint32_t GrGpuGLShaders2::ProgramCache::HashKey::getHash() const {
263 return fHash;
264}
265
266
267struct GrGpuGLShaders2::ShaderCodeSegments {
268 GrSStringBuilder<256> fVSUnis;
269 GrSStringBuilder<256> fVSAttrs;
270 GrSStringBuilder<256> fVaryings;
271 GrSStringBuilder<256> fFSUnis;
272 GrSStringBuilder<512> fVSCode;
273 GrSStringBuilder<512> fFSCode;
274};
275// for variable names etc
276typedef GrSStringBuilder<16> GrTokenString;
277
278#if ATTRIBUTE_MATRIX
279 #define VIEW_MATRIX_NAME "aViewM"
280#else
281 #define VIEW_MATRIX_NAME "uViewM"
282#endif
283
284#define POS_ATTR_NAME "aPosition"
285#define COL_ATTR_NAME "aColor"
286#define TEX_ATTR_NAME "aTexture"
287
288static inline const char* float_vector_type(int count) {
289 static const char* FLOAT_VECS[] = {"ERROR", "float", "vec2", "vec3", "vec4"};
290 GrAssert(count >= 1 && count < GR_ARRAY_COUNT(FLOAT_VECS));
291 return FLOAT_VECS[count];
292}
293
294static inline const char* vector_homog_coord(int count) {
295 static const char* HOMOGS[] = {"ERROR", "", ".y", ".z", ".w"};
296 GrAssert(count >= 1 && count < GR_ARRAY_COUNT(HOMOGS));
297 return HOMOGS[count];
298}
299
300static inline const char* vector_nonhomog_coords(int count) {
301 static const char* NONHOMOGS[] = {"ERROR", "", ".x", ".xy", ".xyz"};
302 GrAssert(count >= 1 && count < GR_ARRAY_COUNT(NONHOMOGS));
303 return NONHOMOGS[count];
304}
305
306static inline const char* vector_all_coords(int count) {
307 static const char* ALL[] = {"ERROR", "", ".xy", ".xyz", ".xyzw"};
308 GrAssert(count >= 1 && count < GR_ARRAY_COUNT(ALL));
309 return ALL[count];
310}
311
312static void tex_matrix_name(int stage, GrStringBuilder* s) {
313#if ATTRIBUTE_MATRIX
314 *s = "aTexM";
315#else
316 *s = "uTexM";
317#endif
318 s->appendInt(stage);
319}
320
321static void sampler_name(int stage, GrStringBuilder* s) {
322 *s = "uSampler";
323 s->appendInt(stage);
324}
325
326static void stage_varying_name(int stage, GrStringBuilder* s) {
327 *s = "vStage";
328 s->appendInt(stage);
329}
330
331static void radial2_param_name(int stage, GrStringBuilder* s) {
332 *s = "uRadial2Params";
333 s->appendInt(stage);
334}
335
336static void radial2_varying_name(int stage, GrStringBuilder* s) {
337 *s = "vB";
338 s->appendInt(stage);
339}
340
341#include "GrRandom.h"
342
343void GrGpuGLShaders2::ProgramUnitTest() {
344 static const uint16_t VFORMATS[] = {
345 0,
346 kSeparateTexCoord_VertexLayoutBit,
347 kPositionAsTexCoord_VertexLayoutBit,
348 kSeparateTexCoord_VertexLayoutBit | kColor_VertexLayoutBit,
349 kPositionAsTexCoord_VertexLayoutBit | kColor_VertexLayoutBit,
350 kTextFormat_VertexLayoutBit
351 };
352 static const int PROG_OPTS[] = {
353 0,
354 ProgramDesc::kNotPoints_OptFlagBit,
355 ProgramDesc::kVertexColorAllOnes_OptFlagBit,
356 ProgramDesc::kNotPoints_OptFlagBit | ProgramDesc::kVertexColorAllOnes_OptFlagBit
357 };
358 static const int STAGE_OPTS[] = {
359 0,
360 StageDesc::kNoPerspective_OptFlagBit,
361 StageDesc::kIdentity_CoordMapping
362 };
363 static const int STAGE_MODULATES[] = {
364 StageDesc::kColor_Modulation,
365 StageDesc::kAlpha_Modulation
366 };
367 static const int STAGE_COORD_MAPPINGS[] = {
368 StageDesc::kIdentity_CoordMapping,
369 StageDesc::kRadialGradient_CoordMapping,
370 StageDesc::kSweepGradient_CoordMapping,
371 StageDesc::kRadial2Gradient_CoordMapping
372 };
373 ProgramDesc pdesc;
374 memset(&pdesc, 0, sizeof(pdesc));
375
376 static const int NUM_TESTS = 1024;
377
378 // GrRandoms nextU() values have patterns in the low bits
379 // So using nextU() % array_count might never take some values.
380 GrRandom random;
381 for (int t = 0; t < NUM_TESTS; ++t) {
382 int x = (int)(random.nextF() * GR_ARRAY_COUNT(VFORMATS));
383 pdesc.fVertexLayout = VFORMATS[x];
384 x = (int)(random.nextF() * GR_ARRAY_COUNT(PROG_OPTS));
385 pdesc.fOptFlags = PROG_OPTS[x];
386 for (int s = 0; s < NUM_STAGES; ++s) {
387 x = (int)(random.nextF() * 2.f);
388 pdesc.fStages[s].fEnabled = x;
389 x = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_OPTS));
390 pdesc.fStages[s].fOptFlags = STAGE_OPTS[x];
391 x = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_MODULATES));
392 pdesc.fStages[s].fModulation = STAGE_MODULATES[x];
393 x = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_COORD_MAPPINGS));
394 pdesc.fStages[s].fCoordMapping = STAGE_COORD_MAPPINGS[x];
395 }
396 Program program;
397 GenProgram(pdesc, &program);
398 DeleteProgram(&program);
399 }
400}
401
402void GrGpuGLShaders2::GenStageCode(int stageNum,
403 const StageDesc& desc,
404 const char* fsInColor, // NULL means no incoming color
405 const char* fsOutColor,
406 const char* vsInCoord,
407 ShaderCodeSegments* segments,
408 StageUniLocations* locations) {
409
410 GrAssert(stageNum >= 0 && stageNum <= 9);
411
412 GrTokenString varyingName;
413 stage_varying_name(stageNum, &varyingName);
414
415 // First decide how many coords are needed to access the texture
416 // Right now it's always 2 but we could start using 1D textures for
417 // gradients.
418 static const int coordDims = 2;
419 int varyingDims;
420 /// Vertex Shader Stuff
421
422 // decide whether we need a matrix to transform texture coords
423 // and whether the varying needs a perspective coord.
424 GrTokenString texMName;
425 tex_matrix_name(stageNum, &texMName);
426 if (desc.fOptFlags & StageDesc::kIdentityMatrix_OptFlagBit) {
427 varyingDims = coordDims;
428 } else {
429 #if ATTRIBUTE_MATRIX
430 segments->fVSAttrs += "attribute mat3 ";
431 segments->fVSAttrs += texMName;
432 segments->fVSAttrs += ";\n";
433 #else
434 segments->fVSUnis += "uniform mat3 ";
435 segments->fVSUnis += texMName;
436 segments->fVSUnis += ";\n";
437 locations->fTextureMatrixUni = 1;
438 #endif
439 if (desc.fOptFlags & StageDesc::kNoPerspective_OptFlagBit) {
440 varyingDims = coordDims;
441 } else {
442 varyingDims = coordDims + 1;
443 }
444 }
445
446 GrTokenString samplerName;
447 sampler_name(stageNum, &samplerName);
448 segments->fFSUnis += "uniform sampler2D ";
449 segments->fFSUnis += samplerName;
450 segments->fFSUnis += ";\n";
451 locations->fSamplerUni = 1;
452
453 segments->fVaryings += "varying ";
454 segments->fVaryings += float_vector_type(varyingDims);
455 segments->fVaryings += " ";
456 segments->fVaryings += varyingName;
457 segments->fVaryings += ";\n";
458
459 if (desc.fOptFlags & StageDesc::kIdentityMatrix_OptFlagBit) {
460 GrAssert(varyingDims == coordDims);
461 segments->fVSCode += "\t";
462 segments->fVSCode += varyingName;
463 segments->fVSCode += " = ";
464 segments->fVSCode += vsInCoord;
465 segments->fVSCode += ";\n";
466 } else {
467 segments->fVSCode += "\t";
468 segments->fVSCode += varyingName;
469 segments->fVSCode += " = (";
470 segments->fVSCode += texMName;
471 segments->fVSCode += " * vec3(";
472 segments->fVSCode += vsInCoord;
473 segments->fVSCode += ", 1))";
474 segments->fVSCode += vector_all_coords(varyingDims);
475 segments->fVSCode += ";\n";
476 }
477
478 GrTokenString radial2ParamsName;
479 radial2_param_name(stageNum, &radial2ParamsName);
480 // for radial grads without perspective we can pass the linear
481 // part of the quadratic as a varying.
482 GrTokenString radial2VaryingName;
483 radial2_varying_name(stageNum, &radial2VaryingName);
484
485 if (StageDesc::kRadial2Gradient_CoordMapping == desc.fCoordMapping) {
486
487 segments->fVSUnis += "uniform " GR_PRECISION " float ";
488 segments->fVSUnis += radial2ParamsName;
489 segments->fVSUnis += "[6];\n";
490
491 segments->fFSUnis += "uniform " GR_PRECISION " float ";
492 segments->fFSUnis += radial2ParamsName;
493 segments->fFSUnis += "[6];\n";
494 locations->fRadial2Uni = 1;
495
496 // if there is perspective we don't interpolate this
497 if (varyingDims == coordDims) {
498 GrAssert(2 == coordDims);
499 segments->fVaryings += "varying float ";
500 segments->fVaryings += radial2VaryingName;
501 segments->fVaryings += ";\n";
502
503 segments->fVSCode += "\t";
504 segments->fVSCode += radial2VaryingName;
505 segments->fVSCode += " = 2.0 * (";
506 segments->fVSCode += radial2ParamsName;
507 segments->fVSCode += "[2] * ";
508 segments->fVSCode += varyingName;
509 segments->fVSCode += ".x ";
510 segments->fVSCode += " - ";
511 segments->fVSCode += radial2ParamsName;
512 segments->fVSCode += "[3]);\n";
513 }
514 }
515
516 /// Fragment Shader Stuff
517 GrTokenString fsCoordName;
518 // function used to access the shader, may be made projective
519 GrTokenString texFunc("texture2D");
520 if (desc.fOptFlags & (StageDesc::kIdentityMatrix_OptFlagBit |
521 StageDesc::kNoPerspective_OptFlagBit)) {
522 GrAssert(varyingDims == coordDims);
523 fsCoordName = varyingName;
524 } else {
525 // if we have to do some non-matrix op on the varyings to get
526 // our final tex coords then when in perspective we have to
527 // do an explicit divide
528 if (StageDesc::kIdentity_CoordMapping == desc.fCoordMapping) {
529 texFunc += "Proj";
530 fsCoordName = varyingName;
531 } else {
532 fsCoordName = "tCoord";
533 fsCoordName.appendInt(stageNum);
534
535 segments->fFSCode += "\t";
536 segments->fFSCode += float_vector_type(coordDims);
537 segments->fFSCode += " ";
538 segments->fFSCode += fsCoordName;
539 segments->fFSCode += " = ";
540 segments->fFSCode += varyingName;
541 segments->fFSCode += vector_nonhomog_coords(varyingDims);
542 segments->fFSCode += " / ";
543 segments->fFSCode += varyingName;
544 segments->fFSCode += vector_homog_coord(varyingDims);
545 segments->fFSCode += ";\n";
546 }
547 }
548
549 GrSStringBuilder<96> sampleCoords;
550 switch (desc.fCoordMapping) {
551 case StageDesc::kIdentity_CoordMapping:
552 sampleCoords = fsCoordName;
553 break;
554 case StageDesc::kSweepGradient_CoordMapping:
555 sampleCoords = "vec2(atan(-";
556 sampleCoords += fsCoordName;
557 sampleCoords += ".y, -";
558 sampleCoords += fsCoordName;
559 sampleCoords += ".x)*0.1591549430918 + 0.5, 0.5)";
560 break;
561 case StageDesc::kRadialGradient_CoordMapping:
562 sampleCoords = "vec2(length(";
563 sampleCoords += fsCoordName;
564 sampleCoords += ".xy), 0.5)";
565 break;
566 case StageDesc::kRadial2Gradient_CoordMapping: {
567 GrTokenString cName = "c";
568 GrTokenString ac4Name = "ac4";
569 GrTokenString rootName = "root";
570
571 cName.appendInt(stageNum);
572 ac4Name.appendInt(stageNum);
573 rootName.appendInt(stageNum);
574
575 GrTokenString bVar;
576 if (coordDims == varyingDims) {
577 bVar = radial2VaryingName;
578 GrAssert(2 == varyingDims);
579 } else {
580 GrAssert(3 == varyingDims);
581 bVar = "b";
582 bVar.appendInt(stageNum);
583 segments->fFSCode += "\tfloat ";
584 segments->fFSCode += bVar;
585 segments->fFSCode += " = 2.0 * (";
586 segments->fFSCode += radial2ParamsName;
587 segments->fFSCode += "[2] * ";
588 segments->fFSCode += fsCoordName;
589 segments->fFSCode += ".x ";
590 segments->fFSCode += " - ";
591 segments->fFSCode += radial2ParamsName;
592 segments->fFSCode += "[3]);\n";
593 }
594
595 segments->fFSCode += "\tfloat ";
596 segments->fFSCode += cName;
597 segments->fFSCode += " = dot(";
598 segments->fFSCode += fsCoordName;
599 segments->fFSCode += ", ";
600 segments->fFSCode += fsCoordName;
601 segments->fFSCode += ") + ";
602 segments->fFSCode += " - ";
603 segments->fFSCode += radial2ParamsName;
604 segments->fFSCode += "[4];\n";
605
606 segments->fFSCode += "\tfloat ";
607 segments->fFSCode += ac4Name;
608 segments->fFSCode += " = ";
609 segments->fFSCode += radial2ParamsName;
610 segments->fFSCode += "[0] * 4.0 * ";
611 segments->fFSCode += cName;
612 segments->fFSCode += ";\n";
613
614 segments->fFSCode += "\tfloat ";
615 segments->fFSCode += rootName;
616 segments->fFSCode += " = sqrt(abs(";
617 segments->fFSCode += bVar;
618 segments->fFSCode += " * ";
619 segments->fFSCode += bVar;
620 segments->fFSCode += " - ";
621 segments->fFSCode += ac4Name;
622 segments->fFSCode += "));\n";
623
624 sampleCoords = "vec2((-";
625 sampleCoords += bVar;
626 sampleCoords += " + ";
627 sampleCoords += radial2ParamsName;
628 sampleCoords += "[5] * ";
629 sampleCoords += rootName;
630 sampleCoords += ") * ";
631 sampleCoords += radial2ParamsName;
632 sampleCoords += "[1], 0.5)\n";
633 break;}
634 };
635
636 segments->fFSCode += "\t";
637 segments->fFSCode += fsOutColor;
638 segments->fFSCode += " = ";
639 if (NULL != fsInColor) {
640 segments->fFSCode += fsInColor;
641 segments->fFSCode += " * ";
642 }
643 segments->fFSCode += texFunc;
644 segments->fFSCode += "(";
645 segments->fFSCode += samplerName;
646 segments->fFSCode += ", ";
647 segments->fFSCode += sampleCoords;
648 segments->fFSCode += ")";
649 if (desc.fModulation == StageDesc::kAlpha_Modulation) {
650 segments->fFSCode += ".aaaa";
651 }
652 segments->fFSCode += ";\n";
653
654}
655
656void GrGpuGLShaders2::GenProgram(const ProgramDesc& desc,
657 Program* program) {
658
659 ShaderCodeSegments segments;
660 const uint32_t& layout = desc.fVertexLayout;
661
662 memset(&program->fUniLocations, 0, sizeof(UniLocations));
663
664 bool haveColor = !(ProgramDesc::kVertexColorAllOnes_OptFlagBit &
665 desc.fOptFlags);
666
667#if ATTRIBUTE_MATRIX
668 segments.fVSAttrs = "attribute mat3 " VIEW_MATRIX_NAME ";\n"
669#else
670 segments.fVSUnis = "uniform mat3 " VIEW_MATRIX_NAME ";\n";
671 segments.fVSAttrs = "";
672#endif
673 segments.fVSAttrs += "attribute vec2 " POS_ATTR_NAME ";\n";
674 if (haveColor) {
675 segments.fVSAttrs += "attribute vec4 " COL_ATTR_NAME ";\n";
676 segments.fVaryings = "varying vec4 vColor;\n";
677 } else {
678 segments.fVaryings = "";
679 }
680
681 segments.fVSCode = "void main() {\n"
682 "\tvec3 pos3 = " VIEW_MATRIX_NAME " * vec3(" POS_ATTR_NAME ", 1);\n"
683 "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n";
684 if (haveColor) {
685 segments.fVSCode += "\tvColor = " COL_ATTR_NAME ";\n";
686 }
687
688 if (!(desc.fOptFlags & ProgramDesc::kNotPoints_OptFlagBit)){
689 segments.fVSCode += "\tgl_PointSize = 1.0;\n";
690 }
691 segments.fFSCode = "void main() {\n";
692
693 bool textureCoordAttr = false;
694 static const char* IN_COORDS[] = {POS_ATTR_NAME, TEX_ATTR_NAME};
695 const char* inCoords = NULL;
696 if ((kSeparateTexCoord_VertexLayoutBit | kTextFormat_VertexLayoutBit) &
697 layout) {
698 segments.fVSAttrs += "attribute vec2 " TEX_ATTR_NAME ";\n";
699 inCoords = IN_COORDS[1];
700 textureCoordAttr = true;
701 } else if (kPositionAsTexCoord_VertexLayoutBit & layout) {
702 inCoords = IN_COORDS[0];
703 }
704
705 GrTokenString inColor = "vColor";
706 GR_STATIC_ASSERT(NUM_STAGES <= 9);
707 int numActiveStages = 0;
708 for (int i = 0; i < NUM_STAGES; ++i) {
709 if (desc.fStages[i].fEnabled) {
710 ++numActiveStages;
711 }
712 }
713 if (NULL != inCoords && numActiveStages) {
714 int currActiveStage = 0;
715 for (int i = 0; i < NUM_STAGES; ++i) {
716 if (desc.fStages[i].fEnabled) {
717 GrTokenString outColor;
718 if (currActiveStage < (numActiveStages - 1)) {
719 outColor = "color";
720 outColor.appendInt(currActiveStage);
721 segments.fFSCode += "\tvec4 ";
722 segments.fFSCode += outColor;
723 segments.fFSCode += ";\n";
724 } else {
725 outColor = "gl_FragColor";
726 }
727 GenStageCode(i,
728 desc.fStages[i],
729 haveColor ? inColor.cstr() : NULL,
730 outColor.cstr(),
731 inCoords,
732 &segments,
733 &program->fUniLocations.fStages[i]);
734 ++currActiveStage;
735 inColor = outColor;
736 haveColor = true;
737 }
738 }
739 } else {
740 segments.fFSCode += "\tgl_FragColor = ";
741 if (haveColor) {
742 segments.fFSCode += inColor;
743 } else {
744 segments.fFSCode += "vec4(1,1,1,1)";
745 }
746 segments.fFSCode += ";\n";
747 }
748 segments.fFSCode += "}\n";
749 segments.fVSCode += "}\n";
750
751
752 const char* strings[4];
753 int lengths[4];
754 int stringCnt = 0;
755
756 if (segments.fVSUnis.length()) {
757 strings[stringCnt] = segments.fVSUnis.cstr();
758 lengths[stringCnt] = segments.fVSUnis.length();
759 ++stringCnt;
760 }
761 if (segments.fVSAttrs.length()) {
762 strings[stringCnt] = segments.fVSAttrs.cstr();
763 lengths[stringCnt] = segments.fVSAttrs.length();
764 ++stringCnt;
765 }
766 if (segments.fVaryings.length()) {
767 strings[stringCnt] = segments.fVaryings.cstr();
768 lengths[stringCnt] = segments.fVaryings.length();
769 ++stringCnt;
770 }
771
772 GrAssert(segments.fVSCode.length());
773 strings[stringCnt] = segments.fVSCode.cstr();
774 lengths[stringCnt] = segments.fVSCode.length();
775 ++stringCnt;
776
777#if PRINT_SHADERS
778 GrPrintf("%s%s%s%s\n",
779 segments.fVSUnis.cstr(),
780 segments.fVSAttrs.cstr(),
781 segments.fVaryings.cstr(),
782 segments.fVSCode.cstr());
783#endif
784 program->fVShaderID = CompileShader(GL_VERTEX_SHADER,
785 stringCnt,
786 strings,
787 lengths);
788
789 stringCnt = 0;
790
791 if (GR_ARRAY_COUNT(GR_SHADER_PRECISION) > 1) {
792 strings[stringCnt] = GR_SHADER_PRECISION;
793 lengths[stringCnt] = GR_ARRAY_COUNT(GR_SHADER_PRECISION) - 1;
794 ++stringCnt;
795 }
796 if (segments.fFSUnis.length()) {
797 strings[stringCnt] = segments.fFSUnis.cstr();
798 lengths[stringCnt] = segments.fFSUnis.length();
799 ++stringCnt;
800 }
801 if (segments.fVaryings.length()) {
802 strings[stringCnt] = segments.fVaryings.cstr();
803 lengths[stringCnt] = segments.fVaryings.length();
804 ++stringCnt;
805 }
806
807 GrAssert(segments.fFSCode.length());
808 strings[stringCnt] = segments.fFSCode.cstr();
809 lengths[stringCnt] = segments.fFSCode.length();
810 ++stringCnt;
811
812#if PRINT_SHADERS
813 GrPrintf("%s%s%s%s\n",
814 GR_SHADER_PRECISION,
815 segments.fFSUnis.cstr(),
816 segments.fVaryings.cstr(),
817 segments.fFSCode.cstr());
818#endif
819 program->fFShaderID = CompileShader(GL_FRAGMENT_SHADER,
820 stringCnt,
821 strings,
822 lengths);
823
824 program->fProgramID = GR_GL(CreateProgram());
825 const GLint& progID = program->fProgramID;
826
827 GR_GL(AttachShader(progID, program->fVShaderID));
828 GR_GL(AttachShader(progID, program->fFShaderID));
829
830 // Bind the attrib locations to same values for all shaders
831 GR_GL(BindAttribLocation(progID, POS_ATTR_LOCATION, POS_ATTR_NAME));
832 if (textureCoordAttr) {
833 GR_GL(BindAttribLocation(progID, TEX_ATTR_LOCATION, TEX_ATTR_NAME));
834 }
835
836#if ATTRIBUTE_MATRIX
837 // set unis to a bogus value so that checks against -1 before
838 // flushing will pass.
839 GR_GL(BindAttribLocation(progID,
840 VIEWMAT_ATTR_LOCATION,
841 VIEW_MATRIX_NAME));
842
843 program->fUniLocations.fViewMatrixUni = BOGUS_MATRIX_UNI_LOCATION;
844
845 for (int i = 0; i < NUM_STAGES; ++i) {
846 if (desc.fStages[i].fEnabled) {
847 GR_GL(BindAttribLocation(progID,
848 TEXMAT_ATTR_LOCATION(i),
849 tex_matrix_name(i).cstr()));
850 program->fUniLocations.fStages[i].fTextureMatrixUni =
851 BOGUS_MATRIX_UNI_LOCATION;
852 }
853 }
854#endif
855
856 GR_GL(BindAttribLocation(progID, COL_ATTR_LOCATION, COL_ATTR_NAME));
857
858 GR_GL(LinkProgram(progID));
859
860 GLint linked;
861 GR_GL(GetProgramiv(progID, GL_LINK_STATUS, &linked));
862 if (!linked) {
863 GLint infoLen;
864 GR_GL(GetProgramiv(progID, GL_INFO_LOG_LENGTH, &infoLen));
865 GrAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
866 if (infoLen > 0) {
867 GR_GL(GetProgramInfoLog(progID,
868 infoLen+1,
869 NULL,
870 (char*)log.get()));
871 GrPrintf((char*)log.get());
872 }
873 GrAssert(!"Error linking program");
874 GR_GL(DeleteProgram(progID));
875 program->fProgramID = 0;
876 return;
877 }
878
879 // Get uniform locations
880#if !ATTRIBUTE_MATRIX
881 program->fUniLocations.fViewMatrixUni =
882 GR_GL(GetUniformLocation(progID, VIEW_MATRIX_NAME));
883 GrAssert(-1 != program->fUniLocations.fViewMatrixUni);
884#endif
885 for (int i = 0; i < NUM_STAGES; ++i) {
886 StageUniLocations& locations = program->fUniLocations.fStages[i];
887 if (desc.fStages[i].fEnabled) {
888#if !ATTRIBUTE_MATRIX
889 if (locations.fTextureMatrixUni) {
890 GrTokenString texMName;
891 tex_matrix_name(i, &texMName);
892 locations.fTextureMatrixUni = GR_GL(GetUniformLocation(
893 progID,
894 texMName.cstr()));
895 GrAssert(-1 != locations.fTextureMatrixUni);
896 } else {
897 locations.fTextureMatrixUni = -1;
898
899 }
900#endif
901
902 if (locations.fSamplerUni) {
903 GrTokenString samplerName;
904 sampler_name(i, &samplerName);
905 locations.fSamplerUni = GR_GL(GetUniformLocation(
906 progID,
907 samplerName.cstr()));
908 GrAssert(-1 != locations.fSamplerUni);
909 } else {
910 locations.fSamplerUni = -1;
911 }
912
913 if (locations.fRadial2Uni) {
914 GrTokenString radial2ParamName;
915 radial2_param_name(i, &radial2ParamName);
916 locations.fRadial2Uni = GR_GL(GetUniformLocation(
917 progID,
918 radial2ParamName.cstr()));
919 GrAssert(-1 != locations.fRadial2Uni);
920 } else {
921 locations.fRadial2Uni = -1;
922 }
923 } else {
924 locations.fSamplerUni = -1;
925 locations.fRadial2Uni = -1;
926 locations.fTextureMatrixUni = -1;
927 }
928 }
929 GR_GL(UseProgram(progID));
930
931 // init sampler unis and set bogus values for state tracking
932 for (int i = 0; i < NUM_STAGES; ++i) {
933 if (-1 != program->fUniLocations.fStages[i].fSamplerUni) {
934 GR_GL(Uniform1i(program->fUniLocations.fStages[i].fSamplerUni, i));
935 }
936 program->fTextureMatrix[i].setScale(GR_ScalarMax, GR_ScalarMax);
937 program->fRadial2CenterX1[i] = GR_ScalarMax;
938 program->fRadial2Radius0[i] = -GR_ScalarMax;
939 }
940 program->fViewMatrix.setScale(GR_ScalarMax, GR_ScalarMax);
941}
942
943void GrGpuGLShaders2::getProgramDesc(PrimitiveType primType, ProgramDesc* desc) {
944
945 // Must initialize all fields or cache will have false negatives!
946 desc->fVertexLayout = fGeometrySrc.fVertexLayout;
947 desc->fStages[0].fEnabled = VertexHasTexCoords(fGeometrySrc.fVertexLayout);
948 for (int i = 1; i < NUM_STAGES; ++i) {
949 desc->fStages[i].fEnabled = false;
950 desc->fStages[i].fOptFlags = 0;
951 desc->fStages[i].fCoordMapping = 0;
952 desc->fStages[i].fModulation = 0;
953 }
954
955 if (primType != kPoints_PrimitiveType) {
956 desc->fOptFlags = ProgramDesc::kNotPoints_OptFlagBit;
957 } else {
958 desc->fOptFlags = 0;
959 }
960#if SKIP_COLOR_MODULATE_OPT
961 if (!(desc->fVertexLayout & kColor_VertexLayoutBit) &&
962 (0xffffffff == fCurrDrawState.fColor)) {
963 desc->fOptFlags |= ProgramDesc::kVertexColorAllOnes_OptFlagBit;
964 }
965#endif
966
967 StageDesc& stage = desc->fStages[0];
968
969 if (stage.fEnabled) {
970 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTexture;
971 GrAssert(NULL != texture);
972 // we matrix to invert when orientation is TopDown, so make sure
973 // we aren't in that case before flagging as identity.
974 if (fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode].isIdentity() &&
975 GrGLTexture::kTopDown_Orientation == texture->orientation()) {
976 stage.fOptFlags = StageDesc::kIdentityMatrix_OptFlagBit;
977 } else if (!fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode].hasPerspective()) {
978 stage.fOptFlags = StageDesc::kNoPerspective_OptFlagBit;
979 } else {
980 stage.fOptFlags = 0;
981 }
982 switch (fCurrDrawState.fSamplerState.getSampleMode()) {
983 case GrSamplerState::kNormal_SampleMode:
984 stage.fCoordMapping = StageDesc::kIdentity_CoordMapping;
985 stage.fModulation = StageDesc::kColor_Modulation;
986 break;
987 case GrSamplerState::kAlphaMod_SampleMode:
988 stage.fCoordMapping = StageDesc::kIdentity_CoordMapping;
989 stage.fModulation = StageDesc::kAlpha_Modulation;
990 break;
991 case GrSamplerState::kRadial_SampleMode:
992 stage.fCoordMapping = StageDesc::kRadialGradient_CoordMapping;
993 stage.fModulation = StageDesc::kColor_Modulation;
994 break;
995 case GrSamplerState::kRadial2_SampleMode:
996 stage.fCoordMapping = StageDesc::kRadial2Gradient_CoordMapping;
997 stage.fModulation = StageDesc::kColor_Modulation;
998 break;
999 case GrSamplerState::kSweep_SampleMode:
1000 stage.fCoordMapping = StageDesc::StageDesc::kSweepGradient_CoordMapping;
1001 stage.fModulation = StageDesc::kColor_Modulation;
1002 break;
1003 default:
1004 GrAssert(!"Unexpected sample mode!");
1005 break;
1006 }
1007 } else {
1008 stage.fOptFlags = 0;
1009 stage.fCoordMapping = 0;
1010 stage.fModulation = 0;
1011 }
1012}
1013
1014GLuint GrGpuGLShaders2::CompileShader(GLenum type,
1015 int stringCnt,
1016 const char** strings,
1017 int* stringLengths) {
1018 GLuint shader = GR_GL(CreateShader(type));
1019 if (0 == shader) {
1020 return 0;
1021 }
1022
1023 GLint compiled;
1024 GR_GL(ShaderSource(shader, stringCnt, strings, stringLengths));
1025 GR_GL(CompileShader(shader));
1026 GR_GL(GetShaderiv(shader, GL_COMPILE_STATUS, &compiled));
1027
1028 if (!compiled) {
1029 GLint infoLen;
1030 GR_GL(GetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen));
1031 GrAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
1032 if (infoLen > 0) {
1033 GR_GL(GetShaderInfoLog(shader, infoLen+1, NULL, (char*)log.get()));
1034 for (int i = 0; i < stringCnt; ++i) {
1035 if (NULL == stringLengths || stringLengths[i] < 0) {
1036 GrPrintf(strings[i]);
1037 } else {
1038 GrPrintf("%.*s", stringLengths[i], strings[i]);
1039 }
1040 }
1041 GrPrintf("\n%s", log.get());
1042 }
1043 GrAssert(!"Shader compilation failed!");
1044 GR_GL(DeleteShader(shader));
1045 return 0;
1046 }
1047 return shader;
1048}
1049
1050void GrGpuGLShaders2::DeleteProgram(Program* program) {
1051 GR_GL(DeleteShader(program->fVShaderID));
1052 GR_GL(DeleteShader(program->fFShaderID));
1053 GR_GL(DeleteProgram(program->fProgramID));
1054 GR_DEBUGCODE(memset(program, 0, sizeof(Program)));
1055}
1056
1057
1058GrGpuGLShaders2::GrGpuGLShaders2() {
1059
1060 resetContextHelper();
1061
1062 fProgram = NULL;
1063 fProgramCache = new ProgramCache();
1064
1065#if GR_DEBUG
1066 ProgramUnitTest();
1067#endif
1068}
1069
1070GrGpuGLShaders2::~GrGpuGLShaders2() {
1071 delete fProgramCache;
1072}
1073
1074void GrGpuGLShaders2::resetContext() {
1075 INHERITED::resetContext();
1076 resetContextHelper();
1077}
1078
1079void GrGpuGLShaders2::resetContextHelper() {
1080 fTextureOrientation = (GrGLTexture::Orientation)-1; // illegal
1081
1082 fHWGeometryState.fVertexLayout = 0;
1083 fHWGeometryState.fPositionPtr = (void*) ~0;
1084 GR_GL(DisableVertexAttribArray(COL_ATTR_LOCATION));
1085 GR_GL(DisableVertexAttribArray(TEX_ATTR_LOCATION));
1086 GR_GL(EnableVertexAttribArray(POS_ATTR_LOCATION));
1087
1088 fHWProgramID = 0;
1089}
1090
1091void GrGpuGLShaders2::flushViewMatrix() {
1092 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1093 GrMatrix m (
1094 GrIntToScalar(2) / fCurrDrawState.fRenderTarget->width(), 0, -GR_Scalar1,
1095 0,-GrIntToScalar(2) / fCurrDrawState.fRenderTarget->height(), GR_Scalar1,
1096 0, 0, GrMatrix::I()[8]);
1097 m.setConcat(m, fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode]);
1098
1099 // ES doesn't allow you to pass true to the transpose param,
1100 // so do our own transpose
1101 GrScalar mt[] = {
1102 m[GrMatrix::kScaleX],
1103 m[GrMatrix::kSkewY],
1104 m[GrMatrix::kPersp0],
1105 m[GrMatrix::kSkewX],
1106 m[GrMatrix::kScaleY],
1107 m[GrMatrix::kPersp1],
1108 m[GrMatrix::kTransX],
1109 m[GrMatrix::kTransY],
1110 m[GrMatrix::kPersp2]
1111 };
1112#if ATTRIBUTE_MATRIX
1113 glVertexAttrib4fv(VIEWMAT_ATTR_LOCATION+0, mt+0);
1114 glVertexAttrib4fv(VIEWMAT_ATTR_LOCATION+1, mt+3);
1115 glVertexAttrib4fv(VIEWMAT_ATTR_LOCATION+2, mt+6);
1116#else
1117 GR_GL(UniformMatrix3fv(fProgram->fUniLocations.fViewMatrixUni,1,false,mt));
1118#endif
1119}
1120
1121void GrGpuGLShaders2::flushTextureMatrix() {
1122
1123 GrAssert(NULL != fCurrDrawState.fTexture);
1124 GrGLTexture::Orientation orientation =
1125 ((GrGLTexture*)fCurrDrawState.fTexture)->orientation();
1126
1127 GrMatrix* m;
1128 GrMatrix temp;
1129 if (GrGLTexture::kBottomUp_Orientation == orientation) {
1130 temp.setAll(
1131 GR_Scalar1, 0, 0,
1132 0, -GR_Scalar1, GR_Scalar1,
1133 0, 0, GrMatrix::I()[8]
1134 );
1135 temp.preConcat(fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode]);
1136 m = &temp;
1137 } else {
1138 GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
1139 m = &fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode];
1140 }
1141
1142 // ES doesn't allow you to pass true to the transpose param,
1143 // so do our own transpose
1144 GrScalar mt[] = {
1145 (*m)[GrMatrix::kScaleX],
1146 (*m)[GrMatrix::kSkewY],
1147 (*m)[GrMatrix::kPersp0],
1148 (*m)[GrMatrix::kSkewX],
1149 (*m)[GrMatrix::kScaleY],
1150 (*m)[GrMatrix::kPersp1],
1151 (*m)[GrMatrix::kTransX],
1152 (*m)[GrMatrix::kTransY],
1153 (*m)[GrMatrix::kPersp2]
1154 };
1155#if ATTRIBUTE_MATRIX
1156 glVertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+0, mt+0);
1157 glVertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+1, mt+3);
1158 glVertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+2, mt+6);
1159#else
1160 GR_GL(UniformMatrix3fv(fProgram->fUniLocations.fStages[0].fTextureMatrixUni,
1161 1,
1162 false,
1163 mt));
1164#endif
1165}
1166
1167void GrGpuGLShaders2::flushRadial2() {
1168
1169 const GrSamplerState& sampler = fCurrDrawState.fSamplerState;
1170
1171 GrScalar centerX1 = sampler.getRadial2CenterX1();
1172 GrScalar radius0 = sampler.getRadial2Radius0();
1173
1174 GrScalar a = GrMul(centerX1, centerX1) - GR_Scalar1;
1175
1176 float unis[6] = {
1177 GrScalarToFloat(a),
1178 1 / (2.f * unis[0]),
1179 GrScalarToFloat(centerX1),
1180 GrScalarToFloat(radius0),
1181 GrScalarToFloat(GrMul(radius0, radius0)),
1182 sampler.isRadial2PosRoot() ? 1.f : -1.f
1183 };
1184 GR_GL(Uniform1fv(fProgram->fUniLocations.fStages[0].fRadial2Uni, 6, unis));
1185}
1186
1187void GrGpuGLShaders2::flushProgram(PrimitiveType type) {
1188 ProgramDesc desc;
1189 getProgramDesc(type, &desc);
1190 fProgram = fProgramCache->getProgram(desc);
1191
1192 if (fHWProgramID != fProgram->fProgramID) {
1193 GR_GL(UseProgram(fProgram->fProgramID));
1194 fHWProgramID = fProgram->fProgramID;
1195#if GR_COLLECT_STATS
1196 ++fStats.fProgChngCnt;
1197#endif
1198 }
1199}
1200
1201bool GrGpuGLShaders2::flushGraphicsState(PrimitiveType type) {
1202
1203 flushGLStateCommon(type);
1204
1205 if (fRenderTargetChanged) {
1206 // our coords are in pixel space and the GL matrices map to NDC
1207 // so if the viewport changed, our matrix is now wrong.
1208#if ATTRIBUTE_MATRIX
1209 fHWDrawState.fMatrixModeCache[kModelView_MatrixMode].setScale(GR_ScalarMax,
1210 GR_ScalarMax);
1211#else
1212 // we assume all shader matrices may be wrong after viewport changes
1213 fProgramCache->invalidateViewMatrices();
1214#endif
1215 fRenderTargetChanged = false;
1216 }
1217
1218 flushProgram(type);
1219
1220 if (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) {
1221 // invalidate the immediate mode color
1222 fHWDrawState.fColor = GrColor_ILLEGAL;
1223 } else {
1224 if (fHWDrawState.fColor != fCurrDrawState.fColor) {
1225 // OpenGL ES only supports the float varities of glVertexAttrib
1226 float c[] = {
1227 GrColorUnpackR(fCurrDrawState.fColor) / 255.f,
1228 GrColorUnpackG(fCurrDrawState.fColor) / 255.f,
1229 GrColorUnpackB(fCurrDrawState.fColor) / 255.f,
1230 GrColorUnpackA(fCurrDrawState.fColor) / 255.f
1231 };
1232 GR_GL(VertexAttrib4fv(COL_ATTR_LOCATION, c));
1233 fHWDrawState.fColor = fCurrDrawState.fColor;
1234 }
1235 }
1236
1237#if ATTRIBUTE_MATRIX
1238 GrMatrix& currViewMatrix = fHWDrawState.fMatrixModeCache[kModelView_MatrixMode];
1239 GrMatrix& currTextureMatrix = fHWDrawState.fMatrixModeCache[kTexture_MatrixMode];
1240 GrGLTexture::Orientation& orientation = fTextureOrientation;
1241#else
1242 GrMatrix& currViewMatrix = fProgram->fViewMatrix;
1243 GrMatrix& currTextureMatrix = fProgram->fTextureMatrix[0];
1244 GrGLTexture::Orientation& orientation = fProgram->fTextureOrientation[0];
1245#endif
1246
1247 if (currViewMatrix != fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode]) {
1248 flushViewMatrix();
1249 currViewMatrix = fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode];
1250 }
1251
1252 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTexture;
1253 if (NULL != texture) {
1254 if (-1 != fProgram->fUniLocations.fStages[0].fTextureMatrixUni &&
1255 (currTextureMatrix !=
1256 fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode] ||
1257 orientation != texture->orientation())) {
1258 flushTextureMatrix();
1259 currTextureMatrix = fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode];
1260 orientation = texture->orientation();
1261 }
1262 }
1263
1264 const GrSamplerState& sampler = fCurrDrawState.fSamplerState;
1265 if (-1 != fProgram->fUniLocations.fStages[0].fRadial2Uni &&
1266 (fProgram->fRadial2CenterX1[0] != sampler.getRadial2CenterX1() ||
1267 fProgram->fRadial2Radius0[0] != sampler.getRadial2Radius0() ||
1268 fProgram->fRadial2PosRoot[0] != sampler.isRadial2PosRoot())) {
1269
1270 flushRadial2();
1271
1272 fProgram->fRadial2CenterX1[0] = sampler.getRadial2CenterX1();
1273 fProgram->fRadial2Radius0[0] = sampler.getRadial2Radius0();
1274 fProgram->fRadial2PosRoot[0] = sampler.isRadial2PosRoot();
1275 }
1276
1277 return true;
1278}
1279
1280void GrGpuGLShaders2::setupGeometry(uint32_t startVertex,
1281 uint32_t startIndex,
1282 uint32_t vertexCount,
1283 uint32_t indexCount) {
1284
1285 int newColorOffset, newTexCoordOffset;
1286
1287 GLsizei newStride = VertexSizeAndOffsets(fGeometrySrc.fVertexLayout,
1288 &newTexCoordOffset,
1289 &newColorOffset);
1290 int oldColorOffset, oldTexCoordOffset;
1291 GLsizei oldStride = VertexSizeAndOffsets(fHWGeometryState.fVertexLayout,
1292 &oldTexCoordOffset,
1293 &oldColorOffset);
1294
1295 const GLvoid* posPtr = (GLvoid*)(newStride * startVertex);
1296
1297 if (kBuffer_GeometrySrcType == fGeometrySrc.fVertexSrc) {
1298 GrAssert(NULL != fGeometrySrc.fVertexBuffer);
1299 GrAssert(!fGeometrySrc.fVertexBuffer->isLocked());
1300 if (fHWGeometryState.fVertexBuffer != fGeometrySrc.fVertexBuffer) {
1301 GrGLVertexBuffer* buf =
1302 (GrGLVertexBuffer*)fGeometrySrc.fVertexBuffer;
1303 GR_GL(BindBuffer(GL_ARRAY_BUFFER, buf->bufferID()));
1304 fHWGeometryState.fVertexBuffer = fGeometrySrc.fVertexBuffer;
1305 }
1306 } else {
1307 if (kArray_GeometrySrcType == fGeometrySrc.fVertexSrc) {
1308 posPtr = (void*)((intptr_t)fGeometrySrc.fVertexArray +
1309 (intptr_t)posPtr);
1310 } else {
1311 GrAssert(kReserved_GeometrySrcType == fGeometrySrc.fVertexSrc);
1312 posPtr = (void*)((intptr_t)fVertices.get() + (intptr_t)posPtr);
1313 }
1314 if (NULL != fHWGeometryState.fVertexBuffer) {
1315 GR_GL(BindBuffer(GL_ARRAY_BUFFER, 0));
1316 fHWGeometryState.fVertexBuffer = NULL;
1317 }
1318 }
1319
1320 if (kBuffer_GeometrySrcType == fGeometrySrc.fIndexSrc) {
1321 GrAssert(NULL != fGeometrySrc.fIndexBuffer);
1322 GrAssert(!fGeometrySrc.fIndexBuffer->isLocked());
1323 if (fHWGeometryState.fIndexBuffer != fGeometrySrc.fIndexBuffer) {
1324 GrGLIndexBuffer* buf =
1325 (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
1326 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf->bufferID()));
1327 fHWGeometryState.fIndexBuffer = fGeometrySrc.fIndexBuffer;
1328 }
1329 } else if (NULL != fHWGeometryState.fIndexBuffer) {
1330 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
1331 fHWGeometryState.fIndexBuffer = NULL;
1332 }
1333
1334 GLenum scalarType;
1335 bool texCoordNorm;
1336 if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) {
1337 scalarType = GrGLTextType;
1338 texCoordNorm = GR_GL_TEXT_TEXTURE_NORMALIZED;
1339 } else {
1340 scalarType = GrGLType;
1341 texCoordNorm = false;
1342 }
1343
1344 bool baseChange = posPtr != fHWGeometryState.fPositionPtr;
1345 bool scalarChange = (GrGLTextType != GrGLType) &&
1346 (kTextFormat_VertexLayoutBit &
1347 (fHWGeometryState.fVertexLayout ^
1348 fGeometrySrc.fVertexLayout));
1349 bool strideChange = newStride != oldStride;
1350 bool posChange = baseChange || scalarChange || strideChange;
1351
1352 if (posChange) {
1353 GR_GL(VertexAttribPointer(POS_ATTR_LOCATION, 2, scalarType,
1354 false, newStride, posPtr));
1355 fHWGeometryState.fPositionPtr = posPtr;
1356 }
1357
1358 if (newTexCoordOffset > 0) {
1359 GLvoid* texCoordPtr = (int8_t*)posPtr + newTexCoordOffset;
1360 if (oldTexCoordOffset <= 0) {
1361 GR_GL(EnableVertexAttribArray(TEX_ATTR_LOCATION));
1362 }
1363 if (posChange || newTexCoordOffset != oldTexCoordOffset) {
1364 GR_GL(VertexAttribPointer(TEX_ATTR_LOCATION, 2, scalarType,
1365 texCoordNorm, newStride, texCoordPtr));
1366 }
1367 } else if (oldTexCoordOffset > 0) {
1368 GR_GL(DisableVertexAttribArray(TEX_ATTR_LOCATION));
1369 }
1370
1371 if (newColorOffset > 0) {
1372 GLvoid* colorPtr = (int8_t*)posPtr + newColorOffset;
1373 if (oldColorOffset <= 0) {
1374 GR_GL(EnableVertexAttribArray(COL_ATTR_LOCATION));
1375 }
1376 if (posChange || newColorOffset != oldColorOffset) {
1377 GR_GL(VertexAttribPointer(COL_ATTR_LOCATION, 4,
1378 GL_UNSIGNED_BYTE,
1379 true, newStride, colorPtr));
1380 }
1381 } else if (oldColorOffset > 0) {
1382 GR_GL(DisableVertexAttribArray(COL_ATTR_LOCATION));
1383 }
1384
1385 fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout;
1386}
1387#endif
1388