blob: b3bfc9a667af7511e260d0a3b9febbfdb7ebb7e8 [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.
reed@google.comac10a2d2010-12-22 21:39:39 +0000195 " gl_FragColor = vColor * texture2DProj(sTexture, vTexture);\n"
reed@google.comac20fb92011-01-12 17:14:53 +0000196
reed@google.comac10a2d2010-12-22 21:39:39 +0000197 "}\n",
198
199 // 2: kText_Program
200 GR_SHADER_PRECISION
201 "varying vec2 vTexture;\n"
202#if ATTRIBUTE_TEXT_COLOR
203 "varying vec4 vColor;\n"
204#else
205 "uniform vec4 uColor;\n"
206#endif
207 "uniform sampler2D sTexture;\n"
208 "void main() {\n"
209#if ATTRIBUTE_TEXT_COLOR
210 " gl_FragColor = vColor * texture2D(sTexture, vTexture).a;\n"
211#else
212 " gl_FragColor = uColor * texture2D(sTexture, vTexture).a;\n"
213#endif
214 "}\n",
215
216 // 3: kNoTexture_Program
217 GR_SHADER_PRECISION
218 "varying vec4 vColor;\n"
219 "void main() {\n"
220 " gl_FragColor = vColor;\n"
221 "}\n",
222
223 // 4: kTextureVertCoordsNoColor_Program
224 GR_SHADER_PRECISION
225 "varying vec3 vTexture;\n"
226 "uniform sampler2D sTexture;\n"
227 "void main() {\n"
228 " gl_FragColor = texture2D(sTexture, vTexture.xy);\n"
229 "}\n",
230
231 // 5: kRadialTextureVertCoords_Program, kRadialTextureTexCoords_Program
232 GR_SHADER_PRECISION
233 "varying vec3 vTexture;\n"
234 "varying vec4 vColor;\n"
235 "uniform sampler2D sTexture;\n"
236 "void main() {\n"
237 " gl_FragColor = vColor * texture2D(sTexture, vec2(length(vTexture.xy), 0.5));\n"
238 "}\n",
239
240 // 6: kSweepTextureVertCoords_Program, kSweepTextureTexCoords_Program
241 GR_SHADER_PRECISION
242 "varying vec3 vTexture;\n"
243 "varying vec4 vColor;\n"
244 "uniform sampler2D sTexture;\n"
245 "void main() {\n"
246 " vec2 t = vec2(atan(-vTexture.y, -vTexture.x)*0.1591549430918 + 0.5,\n"
247 " 0.5);\n"
248 " gl_FragColor = vColor * texture2D(sTexture, t);\n"
249 "}\n",
reed@google.comac20fb92011-01-12 17:14:53 +0000250
reed@google.comac10a2d2010-12-22 21:39:39 +0000251 // 7: kTwoPointRadialTextureVertCoords_Program, kTwoPointRadialTextureTexCoords_Program
252 GR_SHADER_PRECISION
253 "varying vec4 vColor;\n"
254 "varying float vB;\n" // t coeffecient of quadratic.
255 "varying vec2 t;\n" // coordinates in canonical radial gradient space
256 "uniform sampler2D sTexture;\n"
reed@google.comac20fb92011-01-12 17:14:53 +0000257 "uniform float uParams[6];\n"
reed@google.comac10a2d2010-12-22 21:39:39 +0000258 "void main() {\n"
259 "float c = t.x*t.x + t.y*t.y - uParams[4];\n"
260 "float ac4 = uParams[0] * c * 4.0;\n"
261 "float root = sqrt(abs(vB * vB - ac4));\n"
262 "float t = (-vB + uParams[5] * root) * uParams[1];\n"
263 "gl_FragColor = vColor * texture2D(sTexture, vec2(t,0.5))\n;"
264 "}\n",
265};
266
267// determines which frag/vert shaders are used for each program in Programs enum
268
269static const struct {
270 int fVShaderIdx;
271 int fFShaderIdx;
272 bool fHasTexMatrix;
273 bool fHasTexCoords;
274 bool fTwoPointRadial;
reed@google.comac20fb92011-01-12 17:14:53 +0000275 GrGpuGLShaders::ColorType fColorType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000276} gProgramLoadData[] = {
277 // kTextureVertCoords_Program
reed@google.comac20fb92011-01-12 17:14:53 +0000278 {0, 0, true, false, false, GrGpuGLShaders::kAttrib_ColorType },
reed@google.comac10a2d2010-12-22 21:39:39 +0000279 // kTextureVertCoordsProj_Program
reed@google.comac20fb92011-01-12 17:14:53 +0000280 {0, 1, true, false, false, GrGpuGLShaders::kAttrib_ColorType },
reed@google.comac10a2d2010-12-22 21:39:39 +0000281 // kTextureTexCoords_Program
reed@google.comac20fb92011-01-12 17:14:53 +0000282 {1, 0, true, true, false, GrGpuGLShaders::kAttrib_ColorType },
reed@google.comac10a2d2010-12-22 21:39:39 +0000283 // kTextureTexCoordsProj_Program
reed@google.comac20fb92011-01-12 17:14:53 +0000284 {1, 1, true, true, false, GrGpuGLShaders::kAttrib_ColorType },
reed@google.comac10a2d2010-12-22 21:39:39 +0000285 // kTextureVertCoordsNoColor_Program
286 {4, 4, true, false, false, GrGpuGLShaders::kNone_ColorType },
287 // kTextureTexCoordsNoColor_Program
288 {5, 4, true, false, false, GrGpuGLShaders::kNone_ColorType },
289 // kText_Program
290#if ATTRIBUTE_TEXT_COLOR
291 {2, 2, false, true, false, GrGpuGLShaders::kAttrib_ColorType },
292#else
293 {2, 2, false, true, false, GrGpuGLShaders::kUniform_ColorType },
294#endif
295 // kRadialTextureVertCoords_Program
reed@google.comac20fb92011-01-12 17:14:53 +0000296 {0, 5, true, false, false, GrGpuGLShaders::kAttrib_ColorType },
reed@google.comac10a2d2010-12-22 21:39:39 +0000297 // kRadialTextureTexCoords_Program
298 {1, 5, true, true, false, GrGpuGLShaders::kAttrib_ColorType },
299 // kSweepTextureVertCoords_Program
reed@google.comac20fb92011-01-12 17:14:53 +0000300 {0, 6, true, false, false, GrGpuGLShaders::kAttrib_ColorType },
reed@google.comac10a2d2010-12-22 21:39:39 +0000301 // kSweepTextureTexCoords_Program
302 {1, 6, true, true, false, GrGpuGLShaders::kAttrib_ColorType },
303 // kTwoPointRadialTextureVertCoords_Program
304 {6, 7, true, false, true, GrGpuGLShaders::kAttrib_ColorType },
305 // kTwoPointRadialTextureTexCoords_Program
306 {7, 7, true, true, true, GrGpuGLShaders::kAttrib_ColorType },
307 // kNoTexture_Program
308 {3, 3, false, false, false, GrGpuGLShaders::kAttrib_ColorType },
309};
310
311#define GR_GL_POS_ATTR_LOCATION 0
312#define GR_GL_TEX_ATTR_LOCATION 1
313#define GR_GL_COL_ATTR_LOCATION 2
314#if ATTRIBUTE_MATRIX
315 #define GR_GL_MAT_ATTR_LOCATION 3
316 #define GR_GL_TEXMAT_ATTR_LOCATION 6
317#endif
318
319GLuint GrGpuGLShaders::loadShader(GLenum type, const char* src) {
320 GLuint shader = GR_GL(CreateShader(type));
321 if (0 == shader) {
322 return 0;
323 }
324
reed@google.comac10a2d2010-12-22 21:39:39 +0000325 GR_GL(ShaderSource(shader, 1, &src, NULL));
326 GR_GL(CompileShader(shader));
reed@google.comac20fb92011-01-12 17:14:53 +0000327
328 GLint compiled = GR_GL_INIT_ZERO;
reed@google.comac10a2d2010-12-22 21:39:39 +0000329 GR_GL(GetShaderiv(shader, GL_COMPILE_STATUS, &compiled));
330
331 if (!compiled) {
reed@google.comac20fb92011-01-12 17:14:53 +0000332 GLint infoLen = GR_GL_INIT_ZERO;
reed@google.comac10a2d2010-12-22 21:39:39 +0000333 GR_GL(GetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen));
334 GrAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
reed@google.comac20fb92011-01-12 17:14:53 +0000335 if (infoLen > 0) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000336 GR_GL(GetShaderInfoLog(shader, infoLen+1, NULL, (char*)log.get()));
337 GrPrintf((char*)log.get());
338 }
339 GrAssert(!"Shader compilation failed!");
340 GR_GL(DeleteShader(shader));
341 return 0;
342 }
343 return shader;
344}
345
346bool GrGpuGLShaders::createProgram(GLuint vshader, GLuint fshader,
347 bool hasTexMatrix,
348 bool hasTexCoords,
349 GrGpuGLShaders::ColorType colorType,
350 bool twoPointRadial,
351 ProgramData* program) {
352 program->fProgramID = GR_GL(CreateProgram());
353 program->fVShaderID = vshader;
354 program->fFShaderID = fshader;
355
356 GrAssert(0 != program->fProgramID);
reed@google.comac20fb92011-01-12 17:14:53 +0000357
reed@google.comac10a2d2010-12-22 21:39:39 +0000358 GR_GL(AttachShader(program->fProgramID, vshader));
359 GR_GL(AttachShader(program->fProgramID, fshader));
360
reed@google.comac20fb92011-01-12 17:14:53 +0000361 GR_GL(BindAttribLocation(program->fProgramID,
362 GR_GL_POS_ATTR_LOCATION,
reed@google.comac10a2d2010-12-22 21:39:39 +0000363 "aPosition"));
364 if (hasTexCoords) {
reed@google.comac20fb92011-01-12 17:14:53 +0000365 GR_GL(BindAttribLocation(program->fProgramID,
366 GR_GL_TEX_ATTR_LOCATION,
reed@google.comac10a2d2010-12-22 21:39:39 +0000367 "aTexture"));
368 }
369#if ATTRIBUTE_MATRIX
370 if (hasTexMatrix) {
reed@google.comac20fb92011-01-12 17:14:53 +0000371 GR_GL(BindAttribLocation(program->fProgramID,
372 GR_GL_TEXMAT_ATTR_LOCATION,
reed@google.comac10a2d2010-12-22 21:39:39 +0000373 "texM"));
374 // set to something arbitrary to signal to flush that program
375 // uses the texture matrix.
376 program->fTexMatrixLocation = 1000;
377 }
378#endif
379 if (colorType == kAttrib_ColorType) {
reed@google.comac20fb92011-01-12 17:14:53 +0000380 GR_GL(BindAttribLocation(program->fProgramID,
381 GR_GL_COL_ATTR_LOCATION,
reed@google.comac10a2d2010-12-22 21:39:39 +0000382 "aColor"));
383 }
384#if ATTRIBUTE_MATRIX
385 GR_GL(BindAttribLocation(program->fProgramID,
reed@google.comac20fb92011-01-12 17:14:53 +0000386 GR_GL_MAT_ATTR_LOCATION,
reed@google.comac10a2d2010-12-22 21:39:39 +0000387 "viewM"));
388#endif
389
390 GR_GL(LinkProgram(program->fProgramID));
391
reed@google.comac20fb92011-01-12 17:14:53 +0000392 GLint linked = GR_GL_INIT_ZERO;
reed@google.comac10a2d2010-12-22 21:39:39 +0000393 GR_GL(GetProgramiv(program->fProgramID, GL_LINK_STATUS, &linked));
394 if (!linked) {
reed@google.comac20fb92011-01-12 17:14:53 +0000395 GLint infoLen = GR_GL_INIT_ZERO;
reed@google.comac10a2d2010-12-22 21:39:39 +0000396 GR_GL(GetProgramiv(program->fProgramID, GL_INFO_LOG_LENGTH, &infoLen));
397 GrAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
reed@google.comac20fb92011-01-12 17:14:53 +0000398 if (infoLen > 0) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000399 GR_GL(GetProgramInfoLog(program->fProgramID,
reed@google.comac20fb92011-01-12 17:14:53 +0000400 infoLen+1,
401 NULL,
reed@google.comac10a2d2010-12-22 21:39:39 +0000402 (char*)log.get()));
403 GrPrintf((char*)log.get());
404 }
405 GrAssert(!"Error linking program");
406 GR_GL(DeleteProgram(program->fProgramID));
407 program->fProgramID = 0;
408 return false;
409 }
410 program->fColorType = colorType;
411
412#if !ATTRIBUTE_MATRIX
413 program->fMatrixLocation =
414 GR_GL(GetUniformLocation(program->fProgramID, "viewM"));
reed@google.comac20fb92011-01-12 17:14:53 +0000415 program->fTexMatrixLocation =
reed@google.comac10a2d2010-12-22 21:39:39 +0000416 GR_GL(GetUniformLocation(program->fProgramID, "texM"));
417#endif
reed@google.comac20fb92011-01-12 17:14:53 +0000418 program->fColorLocation =
reed@google.comac10a2d2010-12-22 21:39:39 +0000419 GR_GL(GetUniformLocation(program->fProgramID, "uColor"));
reed@google.comac20fb92011-01-12 17:14:53 +0000420 program->fTwoPointParamsLocation =
reed@google.comac10a2d2010-12-22 21:39:39 +0000421 GR_GL(GetUniformLocation(program->fProgramID, "uParams"));
reed@google.comac20fb92011-01-12 17:14:53 +0000422
423 GLint samplerLocation =
reed@google.comac10a2d2010-12-22 21:39:39 +0000424 GR_GL(GetUniformLocation(program->fProgramID, "sTexture"));
425
reed@google.comac20fb92011-01-12 17:14:53 +0000426#if !ATTRIBUTE_MATRIX
reed@google.comac10a2d2010-12-22 21:39:39 +0000427 if (-1 == program->fMatrixLocation) {
428 GrAssert(!"Cannot find matrix uniform in program");
429 GR_GL(DeleteProgram(program->fProgramID));
430 program->fProgramID = 0;
431 return false;
432 }
433#endif
434
435 bool hasTexture = hasTexCoords || hasTexMatrix;
436
437 if (-1 == samplerLocation && hasTexture) {
438 GrAssert(!"Expected to find texture sampler");
439 GR_GL(DeleteProgram(program->fProgramID));
440 program->fProgramID = 0;
441 return false;
442 } else if (-1 != samplerLocation && !hasTexture) {
443 GrAssert(!"unexpectedly found texture sampler");
444 }
reed@google.comf44aa372011-01-19 13:15:36 +0000445#if !ATTRIBUTE_MATRIX && !defined(GR_SKIP_2POINTRADIAL_PROGRAMS)
reed@google.comac10a2d2010-12-22 21:39:39 +0000446 if (-1 == program->fTexMatrixLocation && hasTexMatrix) {
447 GrAssert(!"Expected to find texture matrix");
448 GR_GL(DeleteProgram(program->fProgramID));
449 program->fProgramID = 0;
450 return false;
451 } else if (-1 != program->fTexMatrixLocation && !hasTexMatrix) {
452 GrAssert(!"unexpectedly found texture matrix");
453 }
454#endif
455
reed@google.comac20fb92011-01-12 17:14:53 +0000456 if (-1 == program->fColorLocation &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000457 (kUniform_ColorType == colorType)) {
458 GR_GL(DeleteProgram(program->fProgramID));
459 program->fProgramID = 0;
460 return false;
reed@google.comac20fb92011-01-12 17:14:53 +0000461 } else if (-1 != program->fColorLocation &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000462 (kUniform_ColorType != colorType)) {
463 GrAssert(!"Unexpectedly found color uniform");
464 }
reed@google.comac20fb92011-01-12 17:14:53 +0000465
reed@google.comac10a2d2010-12-22 21:39:39 +0000466 if (twoPointRadial) {
467 if (-1 == program->fTwoPointParamsLocation) {
468 GrAssert(!"Didn't find expected uniform for 2pt radial gradient");
469 GR_GL(DeleteProgram(program->fProgramID));
470 program->fProgramID = 0;
471 return false;
472 }
473 } else {
474 GrAssert(-1 == program->fTwoPointParamsLocation);
475 }
reed@google.comac20fb92011-01-12 17:14:53 +0000476
reed@google.comac10a2d2010-12-22 21:39:39 +0000477 GR_GL(UseProgram(program->fProgramID));
478 if (-1 != samplerLocation) {
479 GR_GL(Uniform1i(samplerLocation, 0));
480 }
reed@google.comac20fb92011-01-12 17:14:53 +0000481
reed@google.comac10a2d2010-12-22 21:39:39 +0000482 return true;
483}
484
485GrGpuGLShaders::GrGpuGLShaders() {
reed@google.comac20fb92011-01-12 17:14:53 +0000486
reed@google.comac10a2d2010-12-22 21:39:39 +0000487 resetContextHelper();
reed@google.comac20fb92011-01-12 17:14:53 +0000488
reed@google.comac10a2d2010-12-22 21:39:39 +0000489 GLuint vshadIDs[GR_ARRAY_COUNT(gvshad)];
490 for (size_t s = 0; s < GR_ARRAY_COUNT(gvshad); ++s) {
491 vshadIDs[s] = loadShader(GL_VERTEX_SHADER, gvshad[s]);
492 }
493
494 GLuint fshadIDs[GR_ARRAY_COUNT(gfshad)];
495 for (size_t s = 0; s < GR_ARRAY_COUNT(gfshad); ++s) {
496 fshadIDs[s] = loadShader(GL_FRAGMENT_SHADER, gfshad[s]);
497 }
498
499 GR_STATIC_ASSERT(kProgramCount == GR_ARRAY_COUNT(gProgramLoadData));
500 for (int p = 0; p < kProgramCount; ++p) {
reed@google.comf44aa372011-01-19 13:15:36 +0000501#ifdef GR_SKIP_2POINTRADIAL_PROGRAMS
502 if (11 == p || 12 == p) continue;
503#endif
reed@google.comac10a2d2010-12-22 21:39:39 +0000504 GR_DEBUGCODE(bool result = )
reed@google.comac20fb92011-01-12 17:14:53 +0000505 createProgram(vshadIDs[gProgramLoadData[p].fVShaderIdx],
reed@google.comac10a2d2010-12-22 21:39:39 +0000506 fshadIDs[gProgramLoadData[p].fFShaderIdx],
507 gProgramLoadData[p].fHasTexMatrix,
508 gProgramLoadData[p].fHasTexCoords,
509 gProgramLoadData[p].fColorType,
510 gProgramLoadData[p].fTwoPointRadial,
511 &fPrograms[p]);
512 GR_DEBUGASSERT(result);
reed@google.comac20fb92011-01-12 17:14:53 +0000513
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000514 fPrograms[p].fViewMatrix.setScale(GR_ScalarMax, GR_ScalarMax);
515 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com316f99232011-01-13 21:28:12 +0000516 fPrograms[p].fTextureMatrices[s].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]);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000562 m.setConcat(m, fCurrDrawState.fViewMatrix);
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
bsalomon@google.com316f99232011-01-13 21:28:12 +0000578 GR_GL(VertexAttrib4fv(GR_GL_MAT_ATTR_LOCATION+0, mt+0));
579 GR_GL(VertexAttrib4fv(GR_GL_MAT_ATTR_LOCATION+1, mt+3));
580 GR_GL(VertexAttrib4fv(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 );
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000596 temp.preConcat(fCurrDrawState.fTextureMatrices[0]);
reed@google.comac10a2d2010-12-22 21:39:39 +0000597 m = &temp;
598 } else {
599 GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000600 m = &fCurrDrawState.fTextureMatrices[0];
reed@google.comac10a2d2010-12-22 21:39:39 +0000601 }
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
bsalomon@google.com316f99232011-01-13 21:28:12 +0000617 GR_GL(VertexAttrib4fv(GR_GL_TEXMAT_ATTR_LOCATION+0, mt+0));
618 GR_GL(VertexAttrib4fv(GR_GL_TEXMAT_ATTR_LOCATION+1, mt+3));
619 GR_GL(VertexAttrib4fv(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
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000647 GrTexture* texture = fCurrDrawState.fTextures[0];
bsalomon@google.com316f99232011-01-13 21:28:12 +0000648 bool posAsTex =
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000649 !!(StagePosAsTexCoordVertexLayoutBit(0) & fGeometrySrc.fVertexLayout);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000650
651 if (!VertexUsesStage(0, fGeometrySrc.fVertexLayout)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000652 goto HAVE_NEXT_PROGRAM;
653 }
654
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000655 GrAssert(NULL != texture);
reed@google.comac10a2d2010-12-22 21:39:39 +0000656
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000657 switch (fCurrDrawState.fSamplerStates[0].getSampleMode()) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000658 case GrSamplerState::kRadial_SampleMode:
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000659 GrAssert(!fCurrDrawState.fTextureMatrices[0].hasPerspective());
660 GrAssert(GrTexture::kAlpha_8_PixelConfig != texture->config());
661 if (posAsTex) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000662 nextProgram = kRadialTextureVertCoords_Program;
663 } else {
664 nextProgram = kRadialTextureTexCoords_Program;
665 }
666 break;
667 case GrSamplerState::kSweep_SampleMode:
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000668 GrAssert(!fCurrDrawState.fTextureMatrices[0].hasPerspective());
669 GrAssert(GrTexture::kAlpha_8_PixelConfig != texture->config());
670 if (posAsTex) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000671 nextProgram = kSweepTextureVertCoords_Program;
672 } else {
673 nextProgram = kSweepTextureTexCoords_Program;
674 }
675 break;
676 case GrSamplerState::kRadial2_SampleMode:
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000677 GrAssert(!fCurrDrawState.fTextureMatrices[0].hasPerspective());
678 GrAssert(GrTexture::kAlpha_8_PixelConfig != texture->config());
679 if (posAsTex) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000680 nextProgram = kTwoPointRadialTextureVertCoords_Program;
681 } else {
682 nextProgram = kTwoPointRadialTextureTexCoords_Program;
683 }
684 break;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000685 case GrSamplerState::kNormal_SampleMode:
686 if (GrTexture::kAlpha_8_PixelConfig == texture->config()) {
bsalomon@google.com316f99232011-01-13 21:28:12 +0000687 GrAssert(((GrGLTexture*)texture)->orientation() ==
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000688 GrGLTexture::kTopDown_Orientation);
689 GrAssert(!posAsTex);
690 nextProgram = kText_Program;
reed@google.comac10a2d2010-12-22 21:39:39 +0000691 } else {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000692 bool persp = fCurrDrawState.fTextureMatrices[0].hasPerspective();
693 if (posAsTex) {
bsalomon@google.com316f99232011-01-13 21:28:12 +0000694 nextProgram = persp ? kTextureVertCoordsProj_Program :
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000695 kTextureVertCoords_Program;
696 } else {
bsalomon@google.com316f99232011-01-13 21:28:12 +0000697 nextProgram = persp ? kTextureTexCoordsProj_Program :
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000698 kTextureTexCoords_Program;
699 }
700 // check for case when frag shader can skip the color modulation
701 if (!persp && !(fGeometrySrc.fVertexLayout
702 & kColor_VertexLayoutBit) &&
703 0xffffffff == fCurrDrawState.fColor) {
704 switch (nextProgram) {
705 case kTextureVertCoords_Program:
706 nextProgram = kTextureVertCoordsNoColor_Program;
707 break;
708 case kTextureTexCoords_Program:
709 nextProgram = kTextureTexCoordsNoColor_Program;
710 break;
711 default:
712 GrAssert("Unexpected");
713 break;
714 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000715 }
716 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000717 break;
reed@google.comac10a2d2010-12-22 21:39:39 +0000718 default:
719 GrAssert(!"Unknown samplemode");
720 break;
721 }
722
723HAVE_NEXT_PROGRAM:
724 if (fHWProgram != nextProgram) {
725 GR_GL(UseProgram(fPrograms[nextProgram].fProgramID));
726 fHWProgram = nextProgram;
727#if GR_COLLECT_STATS
728 ++fStats.fProgChngCnt;
729#endif
730 }
731}
732
733bool GrGpuGLShaders::flushGraphicsState(PrimitiveType type) {
reed@google.comac20fb92011-01-12 17:14:53 +0000734
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000735 for (int s = 1; s < kNumStages; ++s) {
736 if (VertexUsesStage(s, fGeometrySrc.fVertexLayout)) {
bsalomon@google.com316f99232011-01-13 21:28:12 +0000737 unimpl("the hard-coded shaders used by this "
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000738 "class only support 1 stage");
739 return false;
740 }
741 }
742
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000743 if (!flushGLStateCommon(type)) {
744 return false;
745 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000746
747 if (fRenderTargetChanged) {
748 // our coords are in pixel space and the GL matrices map to NDC
749 // so if the viewport changed, our matrix is now wrong.
750#if ATTRIBUTE_MATRIX
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000751 fHWDrawState.fViewMatrix.setScale(GR_ScalarMax, GR_ScalarMax);
reed@google.comac10a2d2010-12-22 21:39:39 +0000752#else
753 // we assume all shader matrices may be wrong after viewport changes
754 for (int p = 0; p < kProgramCount; ++p) {
755 // set to illegal matrix
bsalomon@google.com316f99232011-01-13 21:28:12 +0000756 fPrograms[p].fViewMatrix.setScale(GR_ScalarMax, GR_ScalarMax);
reed@google.comac10a2d2010-12-22 21:39:39 +0000757 }
758#endif
759 fRenderTargetChanged = false;
760 }
reed@google.comac20fb92011-01-12 17:14:53 +0000761
reed@google.comac10a2d2010-12-22 21:39:39 +0000762 flushProgram(type);
763
764 if (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) {
765 // invalidate the immediate mode color
reed@google.comac20fb92011-01-12 17:14:53 +0000766 fHWDrawState.fColor = GrColor_ILLEGAL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000767 } else {
768 // if we don't have per-vert colors either set the color attr
769 // or color uniform (depending on which program).
770 if (-1 != fPrograms[fHWProgram].fColorLocation) {
771 GrAssert(kUniform_ColorType == fPrograms[fHWProgram].fColorType);
772 if (fPrograms[fHWProgram].fColor != fCurrDrawState.fColor) {
773 float c[] = {
774 GrColorUnpackR(fCurrDrawState.fColor) / 255.f,
775 GrColorUnpackG(fCurrDrawState.fColor) / 255.f,
776 GrColorUnpackB(fCurrDrawState.fColor) / 255.f,
777 GrColorUnpackA(fCurrDrawState.fColor) / 255.f
778 };
779 GR_GL(Uniform4fv(fPrograms[fHWProgram].fColorLocation, 1, c));
780 fPrograms[fHWProgram].fColor = fCurrDrawState.fColor;
781 }
reed@google.comac20fb92011-01-12 17:14:53 +0000782 } else if (kAttrib_ColorType == fPrograms[fHWProgram].fColorType &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000783 fHWDrawState.fColor != fCurrDrawState.fColor) {
784 // OpenGL ES only supports the float varities of glVertexAttrib
785 float c[] = {
786 GrColorUnpackR(fCurrDrawState.fColor) / 255.f,
787 GrColorUnpackG(fCurrDrawState.fColor) / 255.f,
788 GrColorUnpackB(fCurrDrawState.fColor) / 255.f,
789 GrColorUnpackA(fCurrDrawState.fColor) / 255.f
790 };
791 GR_GL(VertexAttrib4fv(GR_GL_COL_ATTR_LOCATION, c));
792 fHWDrawState.fColor = fCurrDrawState.fColor;
793 }
794 }
795
796#if ATTRIBUTE_MATRIX
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000797 GrMatrix& currentViewMatrix = fHWDrawState.fViewMatrix;
798 GrMatrix& currentTexMatrix = fHWDrawState.fTextureMatrices[0];
reed@google.comac20fb92011-01-12 17:14:53 +0000799 GrGLTexture::Orientation& orientation = fTextureOrientation;
reed@google.comac10a2d2010-12-22 21:39:39 +0000800#else
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000801 GrMatrix& currentViewMatrix = fPrograms[fHWProgram].fViewMatrix;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000802 GrMatrix& currentTexMatrix = fPrograms[fHWProgram].fTextureMatrices[0];
reed@google.comac20fb92011-01-12 17:14:53 +0000803 GrGLTexture::Orientation& orientation =
reed@google.comac10a2d2010-12-22 21:39:39 +0000804 fPrograms[fHWProgram].fTextureOrientation;
805#endif
806
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000807 if (currentViewMatrix !=
808 fCurrDrawState.fViewMatrix) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000809 flushMatrix(fPrograms[fHWProgram].fMatrixLocation);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000810 currentViewMatrix = fCurrDrawState.fViewMatrix;
reed@google.comac10a2d2010-12-22 21:39:39 +0000811 }
812
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000813 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[0];
reed@google.comac10a2d2010-12-22 21:39:39 +0000814 if (NULL != texture) {
815 if (-1 != fPrograms[fHWProgram].fTexMatrixLocation &&
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000816 (currentTexMatrix != fCurrDrawState.fTextureMatrices[0] ||
reed@google.comac10a2d2010-12-22 21:39:39 +0000817 orientation != texture->orientation())) {
818 flushTexMatrix(fPrograms[fHWProgram].fTexMatrixLocation,
819 texture->orientation());
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000820 currentTexMatrix = fCurrDrawState.fTextureMatrices[0];
reed@google.comac10a2d2010-12-22 21:39:39 +0000821 orientation = texture->orientation();
822 }
823 }
824
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000825 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[0];
reed@google.comac10a2d2010-12-22 21:39:39 +0000826 if (-1 != fPrograms[fHWProgram].fTwoPointParamsLocation &&
827 (fPrograms[fHWProgram].fRadial2CenterX1 != sampler.getRadial2CenterX1() ||
828 fPrograms[fHWProgram].fRadial2Radius0 != sampler.getRadial2Radius0() ||
829 fPrograms[fHWProgram].fRadial2PosRoot != sampler.isRadial2PosRoot())) {
reed@google.comac20fb92011-01-12 17:14:53 +0000830
reed@google.comac10a2d2010-12-22 21:39:39 +0000831 flushTwoPointRadial(fPrograms[fHWProgram].fTwoPointParamsLocation,
832 sampler);
833 fPrograms[fHWProgram].fRadial2CenterX1 = sampler.getRadial2CenterX1();
834 fPrograms[fHWProgram].fRadial2Radius0 = sampler.getRadial2Radius0();
835 fPrograms[fHWProgram].fRadial2PosRoot = sampler.isRadial2PosRoot();
836 }
reed@google.comac20fb92011-01-12 17:14:53 +0000837
reed@google.comac10a2d2010-12-22 21:39:39 +0000838 return true;
839}
840
841void GrGpuGLShaders::setupGeometry(uint32_t startVertex,
842 uint32_t startIndex,
843 uint32_t vertexCount,
844 uint32_t indexCount) {
845
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000846 int newColorOffset;
847 int newTexCoordOffsets[kNumStages];
reed@google.comac20fb92011-01-12 17:14:53 +0000848
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000849 GLsizei newStride = VertexSizeAndOffsetsByStage(fGeometrySrc.fVertexLayout,
bsalomon@google.com316f99232011-01-13 21:28:12 +0000850 newTexCoordOffsets,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000851 &newColorOffset);
852 int oldColorOffset;
853 int oldTexCoordOffsets[kNumStages];
854 GLsizei oldStride = VertexSizeAndOffsetsByStage(fHWGeometryState.fVertexLayout,
bsalomon@google.com316f99232011-01-13 21:28:12 +0000855 oldTexCoordOffsets,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000856 &oldColorOffset);
reed@google.comac20fb92011-01-12 17:14:53 +0000857
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000858 const GLvoid* posPtr = setBuffersAndGetVertexStart(newStride, startVertex,
859 startIndex, vertexCount,
860 indexCount);
reed@google.comac20fb92011-01-12 17:14:53 +0000861
reed@google.comac10a2d2010-12-22 21:39:39 +0000862 GLenum scalarType;
863 bool texCoordNorm;
864 if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) {
865 scalarType = GrGLTextType;
866 texCoordNorm = GR_GL_TEXT_TEXTURE_NORMALIZED;
867 } else {
868 scalarType = GrGLType;
869 texCoordNorm = false;
870 }
reed@google.comac20fb92011-01-12 17:14:53 +0000871
reed@google.comac10a2d2010-12-22 21:39:39 +0000872 bool baseChange = posPtr != fHWGeometryState.fPositionPtr;
873 bool scalarChange = (GrGLTextType != GrGLType) &&
reed@google.comac20fb92011-01-12 17:14:53 +0000874 (kTextFormat_VertexLayoutBit &
875 (fHWGeometryState.fVertexLayout ^
reed@google.comac10a2d2010-12-22 21:39:39 +0000876 fGeometrySrc.fVertexLayout));
877 bool strideChange = newStride != oldStride;
878 bool posChange = baseChange || scalarChange || strideChange;
reed@google.comac20fb92011-01-12 17:14:53 +0000879
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000880 if (fHWGeometryState.fArrayPtrsDirty || posChange) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000881 GR_GL(VertexAttribPointer(GR_GL_POS_ATTR_LOCATION, 2, scalarType,
882 false, newStride, posPtr));
883 fHWGeometryState.fPositionPtr = posPtr;
884 }
reed@google.comac20fb92011-01-12 17:14:53 +0000885
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000886 // this class only supports one stage.
887 if (newTexCoordOffsets[0] > 0) {
888 GLvoid* texCoordPtr = (int8_t*)posPtr + newTexCoordOffsets[0];
889 if (oldTexCoordOffsets[0] <= 0) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000890 GR_GL(EnableVertexAttribArray(GR_GL_TEX_ATTR_LOCATION));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000891 GR_GL(VertexAttribPointer(GR_GL_TEX_ATTR_LOCATION, 2, scalarType,
892 texCoordNorm, newStride, texCoordPtr));
893 } else if (fHWGeometryState.fArrayPtrsDirty || posChange ||
894 newTexCoordOffsets[0] != oldTexCoordOffsets[0]) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000895 GR_GL(VertexAttribPointer(GR_GL_TEX_ATTR_LOCATION, 2, scalarType,
896 texCoordNorm, newStride, texCoordPtr));
897 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000898 } else if (oldTexCoordOffsets[0] > 0) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000899 GR_GL(DisableVertexAttribArray(GR_GL_TEX_ATTR_LOCATION));
900 }
reed@google.comac20fb92011-01-12 17:14:53 +0000901
reed@google.comac10a2d2010-12-22 21:39:39 +0000902 if (newColorOffset > 0) {
903 GLvoid* colorPtr = (int8_t*)posPtr + newColorOffset;
904 if (oldColorOffset <= 0) {
905 GR_GL(EnableVertexAttribArray(GR_GL_COL_ATTR_LOCATION));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000906 GR_GL(VertexAttribPointer(GR_GL_COL_ATTR_LOCATION, 4,
907 GL_UNSIGNED_BYTE,
908 true, newStride, colorPtr));
reed@google.comac10a2d2010-12-22 21:39:39 +0000909 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000910 if (fHWGeometryState.fArrayPtrsDirty || posChange ||
911 newColorOffset != oldColorOffset) {
reed@google.comac20fb92011-01-12 17:14:53 +0000912 GR_GL(VertexAttribPointer(GR_GL_COL_ATTR_LOCATION, 4,
reed@google.comac10a2d2010-12-22 21:39:39 +0000913 GL_UNSIGNED_BYTE,
914 true, newStride, colorPtr));
915 }
916 } else if (oldColorOffset > 0) {
917 GR_GL(DisableVertexAttribArray(GR_GL_COL_ATTR_LOCATION));
918 }
reed@google.comac20fb92011-01-12 17:14:53 +0000919
reed@google.comac10a2d2010-12-22 21:39:39 +0000920 fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000921 fHWGeometryState.fArrayPtrsDirty = false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000922}
923#endif