blob: b9db90c65732a535e1244aa40eb83bd0c292c576 [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 "GrGpuGLShaders.h"
23#include "GrGpuVertex.h"
24#include "GrMemory.h"
25
26#define ATTRIBUTE_MATRIX 0
27
28#define ATTRIBUTE_TEXT_COLOR 1
29
30#if ATTRIBUTE_MATRIX
31 #define DECL_MATRIX(name) "attribute mat3 " #name ";\n"
32#else
33 #define DECL_MATRIX(name) "uniform mat3 " #name ";\n"
34#endif
35
36#define SKIP_CACHE_CHECK true
37
38#if GR_SUPPORT_GLES2
39 #define GR_PRECISION "mediump"
40 #define GR_SHADER_PRECISION "precision mediump float;\n"
41#else
42 #define GR_PRECISION ""
43 #define GR_SHADER_PRECISION ""
44#endif
45
46static const char* gvshad[] = {
47 // 0: kTextureVertCoords_Program, kTextureVertCoordsProj_Program,
48 // kRadialTextureVertCoords_Program, kSweepTextureVertCoords_Program
49 "attribute vec2 aPosition;\n"
50 "attribute vec4 aColor;\n"
51 "varying vec3 vTexture;\n"
52 "varying vec4 vColor;\n"
53 DECL_MATRIX(viewM)
54 DECL_MATRIX(texM)
55 "void main() {\n"
56 " vec3 pos3 = viewM*vec3(aPosition,1);\n"
57 " gl_Position = vec4(pos3.xy,0,pos3.z);\n"
58 " gl_PointSize = 1.0;\n"
59 " vTexture = texM * vec3(aPosition,1);\n"
60 " vColor = aColor;\n"
61 "}\n",
62
63 // 1: kTextureTexCoords_Program, kTextureTexCoordsProj_Program,
64 // kRadialTextureTexCoords_Program, kSweepTextureTexCoords_Program
65 "attribute vec2 aPosition;\n"
66 "attribute vec2 aTexture;\n"
67 "attribute vec4 aColor;\n"
68 "varying vec3 vTexture;\n"
69 "varying vec4 vColor;\n"
70 DECL_MATRIX(viewM)
71 DECL_MATRIX(texM)
72 "void main() {\n"
73 " vec3 pos3 = viewM*vec3(aPosition,1);\n"
74 " gl_Position = vec4(pos3.xy,0,pos3.z);\n"
75 " gl_PointSize = 1.0;\n"
76 " vTexture = texM * vec3(aTexture,1);\n"
77 " vColor = aColor;\n"
78 "}\n",
79
80 // 2: kText_Program
81 "attribute vec2 aPosition;\n"
reed@google.comac20fb92011-01-12 17:14:53 +000082 "attribute vec2 aTexture;\n"
reed@google.comac10a2d2010-12-22 21:39:39 +000083 "varying vec2 vTexture;\n"
84 DECL_MATRIX(viewM)
85#if ATTRIBUTE_TEXT_COLOR
86 "varying vec4 vColor;\n"
87 "attribute vec4 aColor;\n"
88#endif
89 "void main() {\n"
90 " vec3 pos3 = viewM*vec3(aPosition,1);\n"
91 " gl_Position = vec4(pos3.xy,0,pos3.z);\n"
92 " vTexture = aTexture;\n"
93#if ATTRIBUTE_TEXT_COLOR
94 " vColor = aColor;\n"
95#endif
96 "}\n",
97
98 // 3: kNoTexture_Program
99 "attribute vec2 aPosition;\n"
100 "attribute vec4 aColor;\n"
101 "varying vec4 vColor;\n"
102 DECL_MATRIX(viewM)
103 "void main() {\n"
104 " vec3 pos3 = viewM*vec3(aPosition,1);\n"
105 " gl_Position = vec4(pos3.xy,0,pos3.z);\n"
106 " gl_PointSize = 1.0;\n"
107 " vColor = aColor;\n"
108 "}\n",
109
110 // 4: kTextureVertCoordsNoColor_Program
111 "attribute vec2 aPosition;\n"
112 "attribute vec4 aColor;\n"
113 "varying vec3 vTexture;\n"
114 DECL_MATRIX(viewM)
115 DECL_MATRIX(texM)
116 "void main() {\n"
117 " vec3 pos3 = viewM*vec3(aPosition,1);\n"
118 " gl_Position = vec4(pos3.xy,0,pos3.z);\n"
119 " vTexture = texM * vec3(aPosition,1);\n"
120 "}\n",
121
122 // 5: kTextureTexCoordsNoColor_Program
123 "attribute vec2 aPosition;\n"
124 "attribute vec2 aTexture;\n"
125 "varying vec3 vTexture;\n"
126 DECL_MATRIX(viewM)
127 DECL_MATRIX(texM)
128 "void main() {\n"
129 " vec3 pos3 = viewM*vec3(aPosition,1);\n"
130 " gl_Position = vec4(pos3.xy,0,pos3.z);\n"
131 " gl_PointSize = 1.0;\n"
132 " vTexture = texM * vec3(aTexture,1);\n"
133 "}\n",
134
135 // 6: kTwoPointRadialTextureVertCoords_Program
reed@google.comac20fb92011-01-12 17:14:53 +0000136 "uniform " GR_PRECISION " float uParams[6];\n"
137 // 0 is t^2 term of quadratic
reed@google.comac10a2d2010-12-22 21:39:39 +0000138 // 1 is one-half the inverse of above
139 // 2 is x offset of the second circle (post tex-matrix)
140 // 3 is the radius of the first circle (post tex-matrix)
141 // 4 is the first circle radius squared
142 // 5 is 1 to use + in the quadratic eq or -1 to use -
143 DECL_MATRIX(viewM)
144 DECL_MATRIX(texM)
145 "attribute vec2 aPosition;\n"
146 "attribute vec4 aColor;\n"
147 "varying vec4 vColor;\n"
148 "varying float vB;\n" // t coeffecient of quadratic.
149 "varying vec2 t;\n" // coordinates in canonical space
150 "void main() {\n"
151 " vec3 pos3 = viewM*vec3(aPosition,1);\n"
152 " gl_Position = vec4(pos3.xy,0,pos3.z);\n"
153 " t = vec2(texM * vec3(aPosition,1));\n"
154 " vColor = aColor;\n"
155 " vB = 2.0 * (uParams[2] * t.x - uParams[3]);\n"
156 "}\n",
157
158 // 6: kTwoPointRadialTextureVertCoords_Program
reed@google.comac20fb92011-01-12 17:14:53 +0000159 "uniform " GR_PRECISION " float uParams[6];\n"
reed@google.comac10a2d2010-12-22 21:39:39 +0000160 DECL_MATRIX(viewM)
161 DECL_MATRIX(texM)
162 "attribute vec2 aPosition;\n"
163 "attribute vec2 aTexture;\n"
164 "attribute vec4 aColor;\n"
165 "varying vec4 vColor;\n"
166 "varying float vB;\n" // t coeffecient of quadratic.
167 "varying vec2 t;\n" // coordinates in canonical space
168 "void main() {\n"
169 " vec3 pos3 = viewM*vec3(aPosition,1);\n"
170 " gl_Position = vec4(pos3.xy,0,pos3.z);\n"
171 " t = vec2(texM * vec3(aTexture,1));\n"
172 " vColor = aColor;\n"
173 " vB = 2.0 * (uParams[2] * t.x - uParams[3]);\n"
174 "}\n",
175};
176
177static const char* gfshad[] = {
178 // 0: kTextureVertCoords_Program, kTextureTexCoords_Program
179 GR_SHADER_PRECISION
180 "varying vec3 vTexture;\n"
181 "varying vec4 vColor;\n"
182 "uniform sampler2D sTexture;\n"
183 "void main() {\n"
184 " gl_FragColor = vColor * texture2D(sTexture, vTexture.xy);\n"
185 "}\n",
186
187 // 1: kTextureVertCoordsProj_Program, kTextureTexCoordsProj_Program
188 GR_SHADER_PRECISION
189 "varying vec3 vTexture;\n"
190 "varying vec4 vColor;\n"
191 "uniform sampler2D sTexture;\n"
192 "void main() {\n"
193 // On Brian's PC laptop with Intel Gfx texture2DProj seems to be broken
194 // but it works everywhere else tested.
195#if GR_GLSL_2DPROJ_BROKEN
196 " gl_FragColor = vColor * texture2D(sTexture, vTexture.xy / vTexture.z);\n"
197#else
198 " gl_FragColor = vColor * texture2DProj(sTexture, vTexture);\n"
199#endif
reed@google.comac20fb92011-01-12 17:14:53 +0000200
reed@google.comac10a2d2010-12-22 21:39:39 +0000201 "}\n",
202
203 // 2: kText_Program
204 GR_SHADER_PRECISION
205 "varying vec2 vTexture;\n"
206#if ATTRIBUTE_TEXT_COLOR
207 "varying vec4 vColor;\n"
208#else
209 "uniform vec4 uColor;\n"
210#endif
211 "uniform sampler2D sTexture;\n"
212 "void main() {\n"
213#if ATTRIBUTE_TEXT_COLOR
214 " gl_FragColor = vColor * texture2D(sTexture, vTexture).a;\n"
215#else
216 " gl_FragColor = uColor * texture2D(sTexture, vTexture).a;\n"
217#endif
218 "}\n",
219
220 // 3: kNoTexture_Program
221 GR_SHADER_PRECISION
222 "varying vec4 vColor;\n"
223 "void main() {\n"
224 " gl_FragColor = vColor;\n"
225 "}\n",
226
227 // 4: kTextureVertCoordsNoColor_Program
228 GR_SHADER_PRECISION
229 "varying vec3 vTexture;\n"
230 "uniform sampler2D sTexture;\n"
231 "void main() {\n"
232 " gl_FragColor = texture2D(sTexture, vTexture.xy);\n"
233 "}\n",
234
235 // 5: kRadialTextureVertCoords_Program, kRadialTextureTexCoords_Program
236 GR_SHADER_PRECISION
237 "varying vec3 vTexture;\n"
238 "varying vec4 vColor;\n"
239 "uniform sampler2D sTexture;\n"
240 "void main() {\n"
241 " gl_FragColor = vColor * texture2D(sTexture, vec2(length(vTexture.xy), 0.5));\n"
242 "}\n",
243
244 // 6: kSweepTextureVertCoords_Program, kSweepTextureTexCoords_Program
245 GR_SHADER_PRECISION
246 "varying vec3 vTexture;\n"
247 "varying vec4 vColor;\n"
248 "uniform sampler2D sTexture;\n"
249 "void main() {\n"
250 " vec2 t = vec2(atan(-vTexture.y, -vTexture.x)*0.1591549430918 + 0.5,\n"
251 " 0.5);\n"
252 " gl_FragColor = vColor * texture2D(sTexture, t);\n"
253 "}\n",
reed@google.comac20fb92011-01-12 17:14:53 +0000254
reed@google.comac10a2d2010-12-22 21:39:39 +0000255 // 7: kTwoPointRadialTextureVertCoords_Program, kTwoPointRadialTextureTexCoords_Program
256 GR_SHADER_PRECISION
257 "varying vec4 vColor;\n"
258 "varying float vB;\n" // t coeffecient of quadratic.
259 "varying vec2 t;\n" // coordinates in canonical radial gradient space
260 "uniform sampler2D sTexture;\n"
reed@google.comac20fb92011-01-12 17:14:53 +0000261 "uniform float uParams[6];\n"
reed@google.comac10a2d2010-12-22 21:39:39 +0000262 "void main() {\n"
263 "float c = t.x*t.x + t.y*t.y - uParams[4];\n"
264 "float ac4 = uParams[0] * c * 4.0;\n"
265 "float root = sqrt(abs(vB * vB - ac4));\n"
266 "float t = (-vB + uParams[5] * root) * uParams[1];\n"
267 "gl_FragColor = vColor * texture2D(sTexture, vec2(t,0.5))\n;"
268 "}\n",
269};
270
271// determines which frag/vert shaders are used for each program in Programs enum
272
273static const struct {
274 int fVShaderIdx;
275 int fFShaderIdx;
276 bool fHasTexMatrix;
277 bool fHasTexCoords;
278 bool fTwoPointRadial;
reed@google.comac20fb92011-01-12 17:14:53 +0000279 GrGpuGLShaders::ColorType fColorType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000280} gProgramLoadData[] = {
281 // kTextureVertCoords_Program
reed@google.comac20fb92011-01-12 17:14:53 +0000282 {0, 0, true, false, false, GrGpuGLShaders::kAttrib_ColorType },
reed@google.comac10a2d2010-12-22 21:39:39 +0000283 // kTextureVertCoordsProj_Program
reed@google.comac20fb92011-01-12 17:14:53 +0000284 {0, 1, true, false, false, GrGpuGLShaders::kAttrib_ColorType },
reed@google.comac10a2d2010-12-22 21:39:39 +0000285 // kTextureTexCoords_Program
reed@google.comac20fb92011-01-12 17:14:53 +0000286 {1, 0, true, true, false, GrGpuGLShaders::kAttrib_ColorType },
reed@google.comac10a2d2010-12-22 21:39:39 +0000287 // kTextureTexCoordsProj_Program
reed@google.comac20fb92011-01-12 17:14:53 +0000288 {1, 1, true, true, false, GrGpuGLShaders::kAttrib_ColorType },
reed@google.comac10a2d2010-12-22 21:39:39 +0000289 // kTextureVertCoordsNoColor_Program
290 {4, 4, true, false, false, GrGpuGLShaders::kNone_ColorType },
291 // kTextureTexCoordsNoColor_Program
292 {5, 4, true, false, false, GrGpuGLShaders::kNone_ColorType },
293 // kText_Program
294#if ATTRIBUTE_TEXT_COLOR
295 {2, 2, false, true, false, GrGpuGLShaders::kAttrib_ColorType },
296#else
297 {2, 2, false, true, false, GrGpuGLShaders::kUniform_ColorType },
298#endif
299 // kRadialTextureVertCoords_Program
reed@google.comac20fb92011-01-12 17:14:53 +0000300 {0, 5, true, false, false, GrGpuGLShaders::kAttrib_ColorType },
reed@google.comac10a2d2010-12-22 21:39:39 +0000301 // kRadialTextureTexCoords_Program
302 {1, 5, true, true, false, GrGpuGLShaders::kAttrib_ColorType },
303 // kSweepTextureVertCoords_Program
reed@google.comac20fb92011-01-12 17:14:53 +0000304 {0, 6, true, false, false, GrGpuGLShaders::kAttrib_ColorType },
reed@google.comac10a2d2010-12-22 21:39:39 +0000305 // kSweepTextureTexCoords_Program
306 {1, 6, true, true, false, GrGpuGLShaders::kAttrib_ColorType },
307 // kTwoPointRadialTextureVertCoords_Program
308 {6, 7, true, false, true, GrGpuGLShaders::kAttrib_ColorType },
309 // kTwoPointRadialTextureTexCoords_Program
310 {7, 7, true, true, true, GrGpuGLShaders::kAttrib_ColorType },
311 // kNoTexture_Program
312 {3, 3, false, false, false, GrGpuGLShaders::kAttrib_ColorType },
313};
314
315#define GR_GL_POS_ATTR_LOCATION 0
316#define GR_GL_TEX_ATTR_LOCATION 1
317#define GR_GL_COL_ATTR_LOCATION 2
318#if ATTRIBUTE_MATRIX
319 #define GR_GL_MAT_ATTR_LOCATION 3
320 #define GR_GL_TEXMAT_ATTR_LOCATION 6
321#endif
322
323GLuint GrGpuGLShaders::loadShader(GLenum type, const char* src) {
324 GLuint shader = GR_GL(CreateShader(type));
325 if (0 == shader) {
326 return 0;
327 }
328
reed@google.comac10a2d2010-12-22 21:39:39 +0000329 GR_GL(ShaderSource(shader, 1, &src, NULL));
330 GR_GL(CompileShader(shader));
reed@google.comac20fb92011-01-12 17:14:53 +0000331
332 GLint compiled = GR_GL_INIT_ZERO;
reed@google.comac10a2d2010-12-22 21:39:39 +0000333 GR_GL(GetShaderiv(shader, GL_COMPILE_STATUS, &compiled));
334
335 if (!compiled) {
reed@google.comac20fb92011-01-12 17:14:53 +0000336 GLint infoLen = GR_GL_INIT_ZERO;
reed@google.comac10a2d2010-12-22 21:39:39 +0000337 GR_GL(GetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen));
338 GrAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
reed@google.comac20fb92011-01-12 17:14:53 +0000339 if (infoLen > 0) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000340 GR_GL(GetShaderInfoLog(shader, infoLen+1, NULL, (char*)log.get()));
341 GrPrintf((char*)log.get());
342 }
343 GrAssert(!"Shader compilation failed!");
344 GR_GL(DeleteShader(shader));
345 return 0;
346 }
347 return shader;
348}
349
350bool GrGpuGLShaders::createProgram(GLuint vshader, GLuint fshader,
351 bool hasTexMatrix,
352 bool hasTexCoords,
353 GrGpuGLShaders::ColorType colorType,
354 bool twoPointRadial,
355 ProgramData* program) {
356 program->fProgramID = GR_GL(CreateProgram());
357 program->fVShaderID = vshader;
358 program->fFShaderID = fshader;
359
360 GrAssert(0 != program->fProgramID);
reed@google.comac20fb92011-01-12 17:14:53 +0000361
reed@google.comac10a2d2010-12-22 21:39:39 +0000362 GR_GL(AttachShader(program->fProgramID, vshader));
363 GR_GL(AttachShader(program->fProgramID, fshader));
364
reed@google.comac20fb92011-01-12 17:14:53 +0000365 GR_GL(BindAttribLocation(program->fProgramID,
366 GR_GL_POS_ATTR_LOCATION,
reed@google.comac10a2d2010-12-22 21:39:39 +0000367 "aPosition"));
368 if (hasTexCoords) {
reed@google.comac20fb92011-01-12 17:14:53 +0000369 GR_GL(BindAttribLocation(program->fProgramID,
370 GR_GL_TEX_ATTR_LOCATION,
reed@google.comac10a2d2010-12-22 21:39:39 +0000371 "aTexture"));
372 }
373#if ATTRIBUTE_MATRIX
374 if (hasTexMatrix) {
reed@google.comac20fb92011-01-12 17:14:53 +0000375 GR_GL(BindAttribLocation(program->fProgramID,
376 GR_GL_TEXMAT_ATTR_LOCATION,
reed@google.comac10a2d2010-12-22 21:39:39 +0000377 "texM"));
378 // set to something arbitrary to signal to flush that program
379 // uses the texture matrix.
380 program->fTexMatrixLocation = 1000;
381 }
382#endif
383 if (colorType == kAttrib_ColorType) {
reed@google.comac20fb92011-01-12 17:14:53 +0000384 GR_GL(BindAttribLocation(program->fProgramID,
385 GR_GL_COL_ATTR_LOCATION,
reed@google.comac10a2d2010-12-22 21:39:39 +0000386 "aColor"));
387 }
388#if ATTRIBUTE_MATRIX
389 GR_GL(BindAttribLocation(program->fProgramID,
reed@google.comac20fb92011-01-12 17:14:53 +0000390 GR_GL_MAT_ATTR_LOCATION,
reed@google.comac10a2d2010-12-22 21:39:39 +0000391 "viewM"));
392#endif
393
394 GR_GL(LinkProgram(program->fProgramID));
395
reed@google.comac20fb92011-01-12 17:14:53 +0000396 GLint linked = GR_GL_INIT_ZERO;
reed@google.comac10a2d2010-12-22 21:39:39 +0000397 GR_GL(GetProgramiv(program->fProgramID, GL_LINK_STATUS, &linked));
398 if (!linked) {
reed@google.comac20fb92011-01-12 17:14:53 +0000399 GLint infoLen = GR_GL_INIT_ZERO;
reed@google.comac10a2d2010-12-22 21:39:39 +0000400 GR_GL(GetProgramiv(program->fProgramID, GL_INFO_LOG_LENGTH, &infoLen));
401 GrAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
reed@google.comac20fb92011-01-12 17:14:53 +0000402 if (infoLen > 0) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000403 GR_GL(GetProgramInfoLog(program->fProgramID,
reed@google.comac20fb92011-01-12 17:14:53 +0000404 infoLen+1,
405 NULL,
reed@google.comac10a2d2010-12-22 21:39:39 +0000406 (char*)log.get()));
407 GrPrintf((char*)log.get());
408 }
409 GrAssert(!"Error linking program");
410 GR_GL(DeleteProgram(program->fProgramID));
411 program->fProgramID = 0;
412 return false;
413 }
414 program->fColorType = colorType;
415
416#if !ATTRIBUTE_MATRIX
417 program->fMatrixLocation =
418 GR_GL(GetUniformLocation(program->fProgramID, "viewM"));
reed@google.comac20fb92011-01-12 17:14:53 +0000419 program->fTexMatrixLocation =
reed@google.comac10a2d2010-12-22 21:39:39 +0000420 GR_GL(GetUniformLocation(program->fProgramID, "texM"));
421#endif
reed@google.comac20fb92011-01-12 17:14:53 +0000422 program->fColorLocation =
reed@google.comac10a2d2010-12-22 21:39:39 +0000423 GR_GL(GetUniformLocation(program->fProgramID, "uColor"));
reed@google.comac20fb92011-01-12 17:14:53 +0000424 program->fTwoPointParamsLocation =
reed@google.comac10a2d2010-12-22 21:39:39 +0000425 GR_GL(GetUniformLocation(program->fProgramID, "uParams"));
reed@google.comac20fb92011-01-12 17:14:53 +0000426
427 GLint samplerLocation =
reed@google.comac10a2d2010-12-22 21:39:39 +0000428 GR_GL(GetUniformLocation(program->fProgramID, "sTexture"));
429
reed@google.comac20fb92011-01-12 17:14:53 +0000430#if !ATTRIBUTE_MATRIX
reed@google.comac10a2d2010-12-22 21:39:39 +0000431 if (-1 == program->fMatrixLocation) {
432 GrAssert(!"Cannot find matrix uniform in program");
433 GR_GL(DeleteProgram(program->fProgramID));
434 program->fProgramID = 0;
435 return false;
436 }
437#endif
438
439 bool hasTexture = hasTexCoords || hasTexMatrix;
440
441 if (-1 == samplerLocation && hasTexture) {
442 GrAssert(!"Expected to find texture sampler");
443 GR_GL(DeleteProgram(program->fProgramID));
444 program->fProgramID = 0;
445 return false;
446 } else if (-1 != samplerLocation && !hasTexture) {
447 GrAssert(!"unexpectedly found texture sampler");
448 }
449#if !ATTRIBUTE_MATRIX
450 if (-1 == program->fTexMatrixLocation && hasTexMatrix) {
451 GrAssert(!"Expected to find texture matrix");
452 GR_GL(DeleteProgram(program->fProgramID));
453 program->fProgramID = 0;
454 return false;
455 } else if (-1 != program->fTexMatrixLocation && !hasTexMatrix) {
456 GrAssert(!"unexpectedly found texture matrix");
457 }
458#endif
459
reed@google.comac20fb92011-01-12 17:14:53 +0000460 if (-1 == program->fColorLocation &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000461 (kUniform_ColorType == colorType)) {
462 GR_GL(DeleteProgram(program->fProgramID));
463 program->fProgramID = 0;
464 return false;
reed@google.comac20fb92011-01-12 17:14:53 +0000465 } else if (-1 != program->fColorLocation &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000466 (kUniform_ColorType != colorType)) {
467 GrAssert(!"Unexpectedly found color uniform");
468 }
reed@google.comac20fb92011-01-12 17:14:53 +0000469
reed@google.comac10a2d2010-12-22 21:39:39 +0000470 if (twoPointRadial) {
471 if (-1 == program->fTwoPointParamsLocation) {
472 GrAssert(!"Didn't find expected uniform for 2pt radial gradient");
473 GR_GL(DeleteProgram(program->fProgramID));
474 program->fProgramID = 0;
475 return false;
476 }
477 } else {
478 GrAssert(-1 == program->fTwoPointParamsLocation);
479 }
reed@google.comac20fb92011-01-12 17:14:53 +0000480
reed@google.comac10a2d2010-12-22 21:39:39 +0000481 GR_GL(UseProgram(program->fProgramID));
482 if (-1 != samplerLocation) {
483 GR_GL(Uniform1i(samplerLocation, 0));
484 }
reed@google.comac20fb92011-01-12 17:14:53 +0000485
reed@google.comac10a2d2010-12-22 21:39:39 +0000486 return true;
487}
488
489GrGpuGLShaders::GrGpuGLShaders() {
reed@google.comac20fb92011-01-12 17:14:53 +0000490
reed@google.comac10a2d2010-12-22 21:39:39 +0000491 resetContextHelper();
reed@google.comac20fb92011-01-12 17:14:53 +0000492
reed@google.comac10a2d2010-12-22 21:39:39 +0000493 GLuint vshadIDs[GR_ARRAY_COUNT(gvshad)];
494 for (size_t s = 0; s < GR_ARRAY_COUNT(gvshad); ++s) {
495 vshadIDs[s] = loadShader(GL_VERTEX_SHADER, gvshad[s]);
496 }
497
498 GLuint fshadIDs[GR_ARRAY_COUNT(gfshad)];
499 for (size_t s = 0; s < GR_ARRAY_COUNT(gfshad); ++s) {
500 fshadIDs[s] = loadShader(GL_FRAGMENT_SHADER, gfshad[s]);
501 }
502
503 GR_STATIC_ASSERT(kProgramCount == GR_ARRAY_COUNT(gProgramLoadData));
504 for (int p = 0; p < kProgramCount; ++p) {
505 GR_DEBUGCODE(bool result = )
reed@google.comac20fb92011-01-12 17:14:53 +0000506 createProgram(vshadIDs[gProgramLoadData[p].fVShaderIdx],
reed@google.comac10a2d2010-12-22 21:39:39 +0000507 fshadIDs[gProgramLoadData[p].fFShaderIdx],
508 gProgramLoadData[p].fHasTexMatrix,
509 gProgramLoadData[p].fHasTexCoords,
510 gProgramLoadData[p].fColorType,
511 gProgramLoadData[p].fTwoPointRadial,
512 &fPrograms[p]);
513 GR_DEBUGASSERT(result);
reed@google.comac20fb92011-01-12 17:14:53 +0000514
reed@google.comac10a2d2010-12-22 21:39:39 +0000515 for (int m = 0; m < kMatrixModeCount; ++m) {
reed@google.comac20fb92011-01-12 17:14:53 +0000516 fPrograms[p].fMatrixModeCache[m].setScale(GR_ScalarMax,
reed@google.comac10a2d2010-12-22 21:39:39 +0000517 GR_ScalarMax); // illegal
518 };
519 fPrograms[p].fColor = GrColor_ILLEGAL;
520 fPrograms[p].fTextureOrientation = (GrGLTexture::Orientation)-1; // illegal
reed@google.comac20fb92011-01-12 17:14:53 +0000521
reed@google.comac10a2d2010-12-22 21:39:39 +0000522 // these aren't strictly invalid, just really unlikely.
523 fPrograms[p].fRadial2CenterX1 = GR_ScalarMin;
524 fPrograms[p].fRadial2Radius0 = GR_ScalarMin;
525 fPrograms[p].fRadial2PosRoot = true; // arbitrary
526 }
527}
528
529GrGpuGLShaders::~GrGpuGLShaders() {
reed@google.comac20fb92011-01-12 17:14:53 +0000530 // shaders get deleted once for each program that uses them, do we care?
reed@google.comac10a2d2010-12-22 21:39:39 +0000531 // probably not
532 for (int i = 0; i < kProgramCount; ++i) {
533 GR_GL(DeleteProgram(fPrograms[i].fProgramID));
534 GR_GL(DeleteShader(fPrograms[i].fVShaderID));
535 GR_GL(DeleteShader(fPrograms[i].fFShaderID));
536 }
537}
538
539void GrGpuGLShaders::resetContext() {
540 INHERITED::resetContext();
541 resetContextHelper();
542}
543
544void GrGpuGLShaders::resetContextHelper() {
545 fHWProgram = (Programs)-1;
546 fTextureOrientation = (GrGLTexture::Orientation)-1; // illegal
547
548 fHWGeometryState.fVertexLayout = 0;
549 fHWGeometryState.fPositionPtr = (void*) ~0;
550 GR_GL(DisableVertexAttribArray(GR_GL_COL_ATTR_LOCATION));
551 GR_GL(DisableVertexAttribArray(GR_GL_TEX_ATTR_LOCATION));
552 GR_GL(EnableVertexAttribArray(GR_GL_POS_ATTR_LOCATION));
553}
554
555
556void GrGpuGLShaders::flushMatrix(GLint location) {
557 GrAssert(NULL != fCurrDrawState.fRenderTarget);
558 GrMatrix m (
559 GrIntToScalar(2) / fCurrDrawState.fRenderTarget->width(), 0, -GR_Scalar1,
560 0,-GrIntToScalar(2) / fCurrDrawState.fRenderTarget->height(), GR_Scalar1,
561 0, 0, GrMatrix::I()[8]);
562 m.setConcat(m, fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode]);
reed@google.comac20fb92011-01-12 17:14:53 +0000563
564 // ES doesn't allow you to pass true to the transpose param,
reed@google.comac10a2d2010-12-22 21:39:39 +0000565 // so do our own transpose
566 GrScalar mt[] = {
567 m[GrMatrix::kScaleX],
568 m[GrMatrix::kSkewY],
569 m[GrMatrix::kPersp0],
570 m[GrMatrix::kSkewX],
571 m[GrMatrix::kScaleY],
572 m[GrMatrix::kPersp1],
573 m[GrMatrix::kTransX],
574 m[GrMatrix::kTransY],
575 m[GrMatrix::kPersp2]
576 };
577#if ATTRIBUTE_MATRIX
578 glVertexAttrib4fv(GR_GL_MAT_ATTR_LOCATION+0, mt+0);
579 glVertexAttrib4fv(GR_GL_MAT_ATTR_LOCATION+1, mt+3);
580 glVertexAttrib4fv(GR_GL_MAT_ATTR_LOCATION+2, mt+6);
reed@google.comac20fb92011-01-12 17:14:53 +0000581#else
reed@google.comac10a2d2010-12-22 21:39:39 +0000582 GR_GL(UniformMatrix3fv(location,1,false,mt));
583#endif
584}
585
reed@google.comac20fb92011-01-12 17:14:53 +0000586void GrGpuGLShaders::flushTexMatrix(GLint location,
reed@google.comac10a2d2010-12-22 21:39:39 +0000587 GrGLTexture::Orientation orientation) {
588 GrMatrix* m;
589 GrMatrix temp;
590 if (GrGLTexture::kBottomUp_Orientation == orientation) {
591 temp.setAll(
592 GR_Scalar1, 0, 0,
593 0, -GR_Scalar1, GR_Scalar1,
594 0, 0, GrMatrix::I()[8]
595 );
596 temp.preConcat(fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode]);
597 m = &temp;
598 } else {
599 GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
600 m = &fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode];
601 }
602
603 // ES doesn't allow you to pass true to the transpose param,
604 // so do our own transpose
605 GrScalar mt[] = {
606 (*m)[GrMatrix::kScaleX],
607 (*m)[GrMatrix::kSkewY],
608 (*m)[GrMatrix::kPersp0],
609 (*m)[GrMatrix::kSkewX],
610 (*m)[GrMatrix::kScaleY],
611 (*m)[GrMatrix::kPersp1],
612 (*m)[GrMatrix::kTransX],
613 (*m)[GrMatrix::kTransY],
614 (*m)[GrMatrix::kPersp2]
615 };
616#if ATTRIBUTE_MATRIX
617 glVertexAttrib4fv(GR_GL_TEXMAT_ATTR_LOCATION+0, mt+0);
618 glVertexAttrib4fv(GR_GL_TEXMAT_ATTR_LOCATION+1, mt+3);
619 glVertexAttrib4fv(GR_GL_TEXMAT_ATTR_LOCATION+2, mt+6);
reed@google.comac20fb92011-01-12 17:14:53 +0000620#else
reed@google.comac10a2d2010-12-22 21:39:39 +0000621 GR_GL(UniformMatrix3fv(location,1,false,mt));
reed@google.comac20fb92011-01-12 17:14:53 +0000622#endif
reed@google.comac10a2d2010-12-22 21:39:39 +0000623}
624
625void GrGpuGLShaders::flushTwoPointRadial(GLint paramsLocation,
626 const GrSamplerState& state) {
627 GrScalar centerX1 = state.getRadial2CenterX1();
628 GrScalar radius0 = state.getRadial2Radius0();
629
630 GrScalar a = GrMul(centerX1, centerX1) - GR_Scalar1;
631
632 float unis[6] = {
633 GrScalarToFloat(a),
634 1 / (2.f * unis[0]),
635 GrScalarToFloat(centerX1),
636 GrScalarToFloat(radius0),
637 GrScalarToFloat(GrMul(radius0, radius0)),
638 state.isRadial2PosRoot() ? 1.f : -1.f
639 };
640 GR_GL(Uniform1fv(paramsLocation, 6, unis));
641}
642
643void GrGpuGLShaders::flushProgram(PrimitiveType type) {
644
645 Programs nextProgram = kNoTexture_Program;
646
647 if (!VertexHasTexCoords(fGeometrySrc.fVertexLayout)) {
648 goto HAVE_NEXT_PROGRAM;
649 }
650
651 GrAssert(fCurrDrawState.fTexture);
652
653 switch (fCurrDrawState.fSamplerState.getSampleMode()) {
654 case GrSamplerState::kRadial_SampleMode:
655 GrAssert(!fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode].hasPerspective());
656 if (fGeometrySrc.fVertexLayout & kPositionAsTexCoord_VertexLayoutBit) {
657 nextProgram = kRadialTextureVertCoords_Program;
658 } else {
659 nextProgram = kRadialTextureTexCoords_Program;
660 }
661 break;
662 case GrSamplerState::kSweep_SampleMode:
663 GrAssert(!fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode].hasPerspective());
664 if (fGeometrySrc.fVertexLayout & kPositionAsTexCoord_VertexLayoutBit) {
665 nextProgram = kSweepTextureVertCoords_Program;
666 } else {
667 nextProgram = kSweepTextureTexCoords_Program;
668 }
669 break;
670 case GrSamplerState::kRadial2_SampleMode:
671 GrAssert(!fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode].hasPerspective());
672 if (fGeometrySrc.fVertexLayout & kPositionAsTexCoord_VertexLayoutBit) {
673 nextProgram = kTwoPointRadialTextureVertCoords_Program;
674 } else {
675 nextProgram = kTwoPointRadialTextureTexCoords_Program;
676 }
677 break;
678 case GrSamplerState::kAlphaMod_SampleMode:
reed@google.comac20fb92011-01-12 17:14:53 +0000679 GrAssert(((GrGLTexture*)fCurrDrawState.fTexture)->orientation() ==
reed@google.comac10a2d2010-12-22 21:39:39 +0000680 GrGLTexture::kTopDown_Orientation);
681 (((GrGLTexture*)fCurrDrawState.fTexture)->uploadFormat() == GL_ALPHA);
reed@google.comac20fb92011-01-12 17:14:53 +0000682
reed@google.comac10a2d2010-12-22 21:39:39 +0000683 nextProgram = kText_Program;
684 break;
685 case GrSamplerState::kNormal_SampleMode: {
686 GR_DEBUGCODE(GrGLTexture* tex = (GrGLTexture*)fCurrDrawState.fTexture;)
687 GrAssert(tex);
688
689 bool persp = fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode].hasPerspective();
690
691 if (fGeometrySrc.fVertexLayout & kPositionAsTexCoord_VertexLayoutBit) {
reed@google.comac20fb92011-01-12 17:14:53 +0000692 nextProgram = persp ? kTextureVertCoordsProj_Program :
reed@google.comac10a2d2010-12-22 21:39:39 +0000693 kTextureVertCoords_Program;
694 } else {
reed@google.comac20fb92011-01-12 17:14:53 +0000695 nextProgram = persp ? kTextureTexCoordsProj_Program :
reed@google.comac10a2d2010-12-22 21:39:39 +0000696 kTextureTexCoords_Program;
697 }
698 // check for case when frag shader can skip the color modulation
699 if (!persp && !(fGeometrySrc.fVertexLayout
700 & kColor_VertexLayoutBit) &&
701 0xffffffff == fCurrDrawState.fColor) {
702 switch (nextProgram) {
703 case kTextureVertCoords_Program:
704 nextProgram = kTextureVertCoordsNoColor_Program;
705 break;
706 case kTextureTexCoords_Program:
707 nextProgram = kTextureTexCoordsNoColor_Program;
708 break;
709 default:
710 GrAssert("Unexpected");
711 break;
712 }
713 }
714 } break;
715 default:
716 GrAssert(!"Unknown samplemode");
717 break;
718 }
719
720HAVE_NEXT_PROGRAM:
721 if (fHWProgram != nextProgram) {
722 GR_GL(UseProgram(fPrograms[nextProgram].fProgramID));
723 fHWProgram = nextProgram;
724#if GR_COLLECT_STATS
725 ++fStats.fProgChngCnt;
726#endif
727 }
728}
729
730bool GrGpuGLShaders::flushGraphicsState(PrimitiveType type) {
reed@google.comac20fb92011-01-12 17:14:53 +0000731
reed@google.comac10a2d2010-12-22 21:39:39 +0000732 flushGLStateCommon(type);
733
734 if (fRenderTargetChanged) {
735 // our coords are in pixel space and the GL matrices map to NDC
736 // so if the viewport changed, our matrix is now wrong.
737#if ATTRIBUTE_MATRIX
738 fHWDrawState.fMatrixModeCache[kModelView_MatrixMode].setScale(GR_ScalarMax,
739 GR_ScalarMax);
740#else
741 // we assume all shader matrices may be wrong after viewport changes
742 for (int p = 0; p < kProgramCount; ++p) {
743 // set to illegal matrix
reed@google.comac20fb92011-01-12 17:14:53 +0000744 fPrograms[p].fMatrixModeCache[kModelView_MatrixMode].setScale(GR_ScalarMax,
745 GR_ScalarMax);
reed@google.comac10a2d2010-12-22 21:39:39 +0000746 }
747#endif
748 fRenderTargetChanged = false;
749 }
reed@google.comac20fb92011-01-12 17:14:53 +0000750
reed@google.comac10a2d2010-12-22 21:39:39 +0000751 flushProgram(type);
752
753 if (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) {
754 // invalidate the immediate mode color
reed@google.comac20fb92011-01-12 17:14:53 +0000755 fHWDrawState.fColor = GrColor_ILLEGAL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000756 } else {
757 // if we don't have per-vert colors either set the color attr
758 // or color uniform (depending on which program).
759 if (-1 != fPrograms[fHWProgram].fColorLocation) {
760 GrAssert(kUniform_ColorType == fPrograms[fHWProgram].fColorType);
761 if (fPrograms[fHWProgram].fColor != fCurrDrawState.fColor) {
762 float c[] = {
763 GrColorUnpackR(fCurrDrawState.fColor) / 255.f,
764 GrColorUnpackG(fCurrDrawState.fColor) / 255.f,
765 GrColorUnpackB(fCurrDrawState.fColor) / 255.f,
766 GrColorUnpackA(fCurrDrawState.fColor) / 255.f
767 };
768 GR_GL(Uniform4fv(fPrograms[fHWProgram].fColorLocation, 1, c));
769 fPrograms[fHWProgram].fColor = fCurrDrawState.fColor;
770 }
reed@google.comac20fb92011-01-12 17:14:53 +0000771 } else if (kAttrib_ColorType == fPrograms[fHWProgram].fColorType &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000772 fHWDrawState.fColor != fCurrDrawState.fColor) {
773 // OpenGL ES only supports the float varities of glVertexAttrib
774 float c[] = {
775 GrColorUnpackR(fCurrDrawState.fColor) / 255.f,
776 GrColorUnpackG(fCurrDrawState.fColor) / 255.f,
777 GrColorUnpackB(fCurrDrawState.fColor) / 255.f,
778 GrColorUnpackA(fCurrDrawState.fColor) / 255.f
779 };
780 GR_GL(VertexAttrib4fv(GR_GL_COL_ATTR_LOCATION, c));
781 fHWDrawState.fColor = fCurrDrawState.fColor;
782 }
783 }
784
785#if ATTRIBUTE_MATRIX
786 GrMatrix* currentMats = fHWDrawState.fMatrixModeCache;
reed@google.comac20fb92011-01-12 17:14:53 +0000787 GrGLTexture::Orientation& orientation = fTextureOrientation;
reed@google.comac10a2d2010-12-22 21:39:39 +0000788#else
789 GrMatrix* currentMats = fPrograms[fHWProgram].fMatrixModeCache;
reed@google.comac20fb92011-01-12 17:14:53 +0000790 GrGLTexture::Orientation& orientation =
reed@google.comac10a2d2010-12-22 21:39:39 +0000791 fPrograms[fHWProgram].fTextureOrientation;
792#endif
793
794 if (currentMats[kModelView_MatrixMode] !=
795 fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode]) {
796 flushMatrix(fPrograms[fHWProgram].fMatrixLocation);
reed@google.comac20fb92011-01-12 17:14:53 +0000797 currentMats[kModelView_MatrixMode] =
reed@google.comac10a2d2010-12-22 21:39:39 +0000798 fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode];
799 }
800
801 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTexture;
802 if (NULL != texture) {
803 if (-1 != fPrograms[fHWProgram].fTexMatrixLocation &&
804 (currentMats[kTexture_MatrixMode] !=
805 fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode] ||
806 orientation != texture->orientation())) {
807 flushTexMatrix(fPrograms[fHWProgram].fTexMatrixLocation,
808 texture->orientation());
reed@google.comac20fb92011-01-12 17:14:53 +0000809 currentMats[kTexture_MatrixMode] =
reed@google.comac10a2d2010-12-22 21:39:39 +0000810 fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode];
811 orientation = texture->orientation();
812 }
813 }
814
815 const GrSamplerState& sampler = fCurrDrawState.fSamplerState;
816 if (-1 != fPrograms[fHWProgram].fTwoPointParamsLocation &&
817 (fPrograms[fHWProgram].fRadial2CenterX1 != sampler.getRadial2CenterX1() ||
818 fPrograms[fHWProgram].fRadial2Radius0 != sampler.getRadial2Radius0() ||
819 fPrograms[fHWProgram].fRadial2PosRoot != sampler.isRadial2PosRoot())) {
reed@google.comac20fb92011-01-12 17:14:53 +0000820
reed@google.comac10a2d2010-12-22 21:39:39 +0000821 flushTwoPointRadial(fPrograms[fHWProgram].fTwoPointParamsLocation,
822 sampler);
823 fPrograms[fHWProgram].fRadial2CenterX1 = sampler.getRadial2CenterX1();
824 fPrograms[fHWProgram].fRadial2Radius0 = sampler.getRadial2Radius0();
825 fPrograms[fHWProgram].fRadial2PosRoot = sampler.isRadial2PosRoot();
826 }
reed@google.comac20fb92011-01-12 17:14:53 +0000827
reed@google.comac10a2d2010-12-22 21:39:39 +0000828 return true;
829}
830
831void GrGpuGLShaders::setupGeometry(uint32_t startVertex,
832 uint32_t startIndex,
833 uint32_t vertexCount,
834 uint32_t indexCount) {
835
836 int newColorOffset, newTexCoordOffset;
reed@google.comac20fb92011-01-12 17:14:53 +0000837
reed@google.comac10a2d2010-12-22 21:39:39 +0000838 GLsizei newStride = VertexSizeAndOffsets(fGeometrySrc.fVertexLayout,
reed@google.comac20fb92011-01-12 17:14:53 +0000839 &newTexCoordOffset,
reed@google.comac10a2d2010-12-22 21:39:39 +0000840 &newColorOffset);
841 int oldColorOffset, oldTexCoordOffset;
842 GLsizei oldStride = VertexSizeAndOffsets(fHWGeometryState.fVertexLayout,
reed@google.comac20fb92011-01-12 17:14:53 +0000843 &oldTexCoordOffset,
reed@google.comac10a2d2010-12-22 21:39:39 +0000844 &oldColorOffset);
reed@google.comac20fb92011-01-12 17:14:53 +0000845
reed@google.comac10a2d2010-12-22 21:39:39 +0000846 const GLvoid* posPtr = (GLvoid*)(newStride * startVertex);
reed@google.comac20fb92011-01-12 17:14:53 +0000847
reed@google.comac10a2d2010-12-22 21:39:39 +0000848 if (kBuffer_GeometrySrcType == fGeometrySrc.fVertexSrc) {
849 GrAssert(NULL != fGeometrySrc.fVertexBuffer);
850 GrAssert(!fGeometrySrc.fVertexBuffer->isLocked());
851 if (fHWGeometryState.fVertexBuffer != fGeometrySrc.fVertexBuffer) {
reed@google.comac20fb92011-01-12 17:14:53 +0000852 GrGLVertexBuffer* buf =
reed@google.comac10a2d2010-12-22 21:39:39 +0000853 (GrGLVertexBuffer*)fGeometrySrc.fVertexBuffer;
854 GR_GL(BindBuffer(GL_ARRAY_BUFFER, buf->bufferID()));
855 fHWGeometryState.fVertexBuffer = fGeometrySrc.fVertexBuffer;
856 }
reed@google.comac20fb92011-01-12 17:14:53 +0000857 } else {
reed@google.comac10a2d2010-12-22 21:39:39 +0000858 if (kArray_GeometrySrcType == fGeometrySrc.fVertexSrc) {
reed@google.comac20fb92011-01-12 17:14:53 +0000859 posPtr = (void*)((intptr_t)fGeometrySrc.fVertexArray +
reed@google.comac10a2d2010-12-22 21:39:39 +0000860 (intptr_t)posPtr);
861 } else {
862 GrAssert(kReserved_GeometrySrcType == fGeometrySrc.fVertexSrc);
reed@google.comac20fb92011-01-12 17:14:53 +0000863 posPtr = (void*)((intptr_t)fVertices.get() + (intptr_t)posPtr);
reed@google.comac10a2d2010-12-22 21:39:39 +0000864 }
865 if (NULL != fHWGeometryState.fVertexBuffer) {
866 GR_GL(BindBuffer(GL_ARRAY_BUFFER, 0));
867 fHWGeometryState.fVertexBuffer = NULL;
868 }
869 }
reed@google.comac20fb92011-01-12 17:14:53 +0000870
reed@google.comac10a2d2010-12-22 21:39:39 +0000871 if (kBuffer_GeometrySrcType == fGeometrySrc.fIndexSrc) {
872 GrAssert(NULL != fGeometrySrc.fIndexBuffer);
873 GrAssert(!fGeometrySrc.fIndexBuffer->isLocked());
874 if (fHWGeometryState.fIndexBuffer != fGeometrySrc.fIndexBuffer) {
reed@google.comac20fb92011-01-12 17:14:53 +0000875 GrGLIndexBuffer* buf =
reed@google.comac10a2d2010-12-22 21:39:39 +0000876 (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
877 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf->bufferID()));
878 fHWGeometryState.fIndexBuffer = fGeometrySrc.fIndexBuffer;
879 }
880 } else if (NULL != fHWGeometryState.fIndexBuffer) {
881 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
882 fHWGeometryState.fIndexBuffer = NULL;
883 }
reed@google.comac20fb92011-01-12 17:14:53 +0000884
reed@google.comac10a2d2010-12-22 21:39:39 +0000885 GLenum scalarType;
886 bool texCoordNorm;
887 if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) {
888 scalarType = GrGLTextType;
889 texCoordNorm = GR_GL_TEXT_TEXTURE_NORMALIZED;
890 } else {
891 scalarType = GrGLType;
892 texCoordNorm = false;
893 }
reed@google.comac20fb92011-01-12 17:14:53 +0000894
reed@google.comac10a2d2010-12-22 21:39:39 +0000895 bool baseChange = posPtr != fHWGeometryState.fPositionPtr;
896 bool scalarChange = (GrGLTextType != GrGLType) &&
reed@google.comac20fb92011-01-12 17:14:53 +0000897 (kTextFormat_VertexLayoutBit &
898 (fHWGeometryState.fVertexLayout ^
reed@google.comac10a2d2010-12-22 21:39:39 +0000899 fGeometrySrc.fVertexLayout));
900 bool strideChange = newStride != oldStride;
901 bool posChange = baseChange || scalarChange || strideChange;
reed@google.comac20fb92011-01-12 17:14:53 +0000902
reed@google.comac10a2d2010-12-22 21:39:39 +0000903 if (posChange) {
904 GR_GL(VertexAttribPointer(GR_GL_POS_ATTR_LOCATION, 2, scalarType,
905 false, newStride, posPtr));
906 fHWGeometryState.fPositionPtr = posPtr;
907 }
reed@google.comac20fb92011-01-12 17:14:53 +0000908
reed@google.comac10a2d2010-12-22 21:39:39 +0000909 if (newTexCoordOffset > 0) {
910 GLvoid* texCoordPtr = (int8_t*)posPtr + newTexCoordOffset;
911 if (oldTexCoordOffset <= 0) {
912 GR_GL(EnableVertexAttribArray(GR_GL_TEX_ATTR_LOCATION));
913 }
914 if (posChange || newTexCoordOffset != oldTexCoordOffset) {
915 GR_GL(VertexAttribPointer(GR_GL_TEX_ATTR_LOCATION, 2, scalarType,
916 texCoordNorm, newStride, texCoordPtr));
917 }
918 } else if (oldTexCoordOffset > 0) {
919 GR_GL(DisableVertexAttribArray(GR_GL_TEX_ATTR_LOCATION));
920 }
reed@google.comac20fb92011-01-12 17:14:53 +0000921
reed@google.comac10a2d2010-12-22 21:39:39 +0000922 if (newColorOffset > 0) {
923 GLvoid* colorPtr = (int8_t*)posPtr + newColorOffset;
924 if (oldColorOffset <= 0) {
925 GR_GL(EnableVertexAttribArray(GR_GL_COL_ATTR_LOCATION));
926 }
927 if (posChange || newColorOffset != oldColorOffset) {
reed@google.comac20fb92011-01-12 17:14:53 +0000928 GR_GL(VertexAttribPointer(GR_GL_COL_ATTR_LOCATION, 4,
reed@google.comac10a2d2010-12-22 21:39:39 +0000929 GL_UNSIGNED_BYTE,
930 true, newStride, colorPtr));
931 }
932 } else if (oldColorOffset > 0) {
933 GR_GL(DisableVertexAttribArray(GR_GL_COL_ATTR_LOCATION));
934 }
reed@google.comac20fb92011-01-12 17:14:53 +0000935
reed@google.comac10a2d2010-12-22 21:39:39 +0000936 fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout;
937}
938#endif