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