blob: 03d46741c94cd1850a6908d2c906c3282ef91104 [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
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000515 fPrograms[p].fViewMatrix.setScale(GR_ScalarMax, GR_ScalarMax);
516 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com316f99232011-01-13 21:28:12 +0000517 fPrograms[p].fTextureMatrices[s].setScale(GR_ScalarMax,
reed@google.comac10a2d2010-12-22 21:39:39 +0000518 GR_ScalarMax); // illegal
519 };
520 fPrograms[p].fColor = GrColor_ILLEGAL;
521 fPrograms[p].fTextureOrientation = (GrGLTexture::Orientation)-1; // illegal
reed@google.comac20fb92011-01-12 17:14:53 +0000522
reed@google.comac10a2d2010-12-22 21:39:39 +0000523 // these aren't strictly invalid, just really unlikely.
524 fPrograms[p].fRadial2CenterX1 = GR_ScalarMin;
525 fPrograms[p].fRadial2Radius0 = GR_ScalarMin;
526 fPrograms[p].fRadial2PosRoot = true; // arbitrary
527 }
528}
529
530GrGpuGLShaders::~GrGpuGLShaders() {
reed@google.comac20fb92011-01-12 17:14:53 +0000531 // shaders get deleted once for each program that uses them, do we care?
reed@google.comac10a2d2010-12-22 21:39:39 +0000532 // probably not
533 for (int i = 0; i < kProgramCount; ++i) {
534 GR_GL(DeleteProgram(fPrograms[i].fProgramID));
535 GR_GL(DeleteShader(fPrograms[i].fVShaderID));
536 GR_GL(DeleteShader(fPrograms[i].fFShaderID));
537 }
538}
539
540void GrGpuGLShaders::resetContext() {
541 INHERITED::resetContext();
542 resetContextHelper();
543}
544
545void GrGpuGLShaders::resetContextHelper() {
546 fHWProgram = (Programs)-1;
547 fTextureOrientation = (GrGLTexture::Orientation)-1; // illegal
548
549 fHWGeometryState.fVertexLayout = 0;
550 fHWGeometryState.fPositionPtr = (void*) ~0;
551 GR_GL(DisableVertexAttribArray(GR_GL_COL_ATTR_LOCATION));
552 GR_GL(DisableVertexAttribArray(GR_GL_TEX_ATTR_LOCATION));
553 GR_GL(EnableVertexAttribArray(GR_GL_POS_ATTR_LOCATION));
554}
555
556
557void GrGpuGLShaders::flushMatrix(GLint location) {
558 GrAssert(NULL != fCurrDrawState.fRenderTarget);
559 GrMatrix m (
560 GrIntToScalar(2) / fCurrDrawState.fRenderTarget->width(), 0, -GR_Scalar1,
561 0,-GrIntToScalar(2) / fCurrDrawState.fRenderTarget->height(), GR_Scalar1,
562 0, 0, GrMatrix::I()[8]);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000563 m.setConcat(m, fCurrDrawState.fViewMatrix);
reed@google.comac20fb92011-01-12 17:14:53 +0000564
565 // ES doesn't allow you to pass true to the transpose param,
reed@google.comac10a2d2010-12-22 21:39:39 +0000566 // so do our own transpose
567 GrScalar mt[] = {
568 m[GrMatrix::kScaleX],
569 m[GrMatrix::kSkewY],
570 m[GrMatrix::kPersp0],
571 m[GrMatrix::kSkewX],
572 m[GrMatrix::kScaleY],
573 m[GrMatrix::kPersp1],
574 m[GrMatrix::kTransX],
575 m[GrMatrix::kTransY],
576 m[GrMatrix::kPersp2]
577 };
578#if ATTRIBUTE_MATRIX
bsalomon@google.com316f99232011-01-13 21:28:12 +0000579 GR_GL(VertexAttrib4fv(GR_GL_MAT_ATTR_LOCATION+0, mt+0));
580 GR_GL(VertexAttrib4fv(GR_GL_MAT_ATTR_LOCATION+1, mt+3));
581 GR_GL(VertexAttrib4fv(GR_GL_MAT_ATTR_LOCATION+2, mt+6));
reed@google.comac20fb92011-01-12 17:14:53 +0000582#else
reed@google.comac10a2d2010-12-22 21:39:39 +0000583 GR_GL(UniformMatrix3fv(location,1,false,mt));
584#endif
585}
586
reed@google.comac20fb92011-01-12 17:14:53 +0000587void GrGpuGLShaders::flushTexMatrix(GLint location,
reed@google.comac10a2d2010-12-22 21:39:39 +0000588 GrGLTexture::Orientation orientation) {
589 GrMatrix* m;
590 GrMatrix temp;
591 if (GrGLTexture::kBottomUp_Orientation == orientation) {
592 temp.setAll(
593 GR_Scalar1, 0, 0,
594 0, -GR_Scalar1, GR_Scalar1,
595 0, 0, GrMatrix::I()[8]
596 );
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000597 temp.preConcat(fCurrDrawState.fTextureMatrices[0]);
reed@google.comac10a2d2010-12-22 21:39:39 +0000598 m = &temp;
599 } else {
600 GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000601 m = &fCurrDrawState.fTextureMatrices[0];
reed@google.comac10a2d2010-12-22 21:39:39 +0000602 }
603
604 // ES doesn't allow you to pass true to the transpose param,
605 // so do our own transpose
606 GrScalar mt[] = {
607 (*m)[GrMatrix::kScaleX],
608 (*m)[GrMatrix::kSkewY],
609 (*m)[GrMatrix::kPersp0],
610 (*m)[GrMatrix::kSkewX],
611 (*m)[GrMatrix::kScaleY],
612 (*m)[GrMatrix::kPersp1],
613 (*m)[GrMatrix::kTransX],
614 (*m)[GrMatrix::kTransY],
615 (*m)[GrMatrix::kPersp2]
616 };
617#if ATTRIBUTE_MATRIX
bsalomon@google.com316f99232011-01-13 21:28:12 +0000618 GR_GL(VertexAttrib4fv(GR_GL_TEXMAT_ATTR_LOCATION+0, mt+0));
619 GR_GL(VertexAttrib4fv(GR_GL_TEXMAT_ATTR_LOCATION+1, mt+3));
620 GR_GL(VertexAttrib4fv(GR_GL_TEXMAT_ATTR_LOCATION+2, mt+6));
reed@google.comac20fb92011-01-12 17:14:53 +0000621#else
reed@google.comac10a2d2010-12-22 21:39:39 +0000622 GR_GL(UniformMatrix3fv(location,1,false,mt));
reed@google.comac20fb92011-01-12 17:14:53 +0000623#endif
reed@google.comac10a2d2010-12-22 21:39:39 +0000624}
625
626void GrGpuGLShaders::flushTwoPointRadial(GLint paramsLocation,
627 const GrSamplerState& state) {
628 GrScalar centerX1 = state.getRadial2CenterX1();
629 GrScalar radius0 = state.getRadial2Radius0();
630
631 GrScalar a = GrMul(centerX1, centerX1) - GR_Scalar1;
632
633 float unis[6] = {
634 GrScalarToFloat(a),
635 1 / (2.f * unis[0]),
636 GrScalarToFloat(centerX1),
637 GrScalarToFloat(radius0),
638 GrScalarToFloat(GrMul(radius0, radius0)),
639 state.isRadial2PosRoot() ? 1.f : -1.f
640 };
641 GR_GL(Uniform1fv(paramsLocation, 6, unis));
642}
643
644void GrGpuGLShaders::flushProgram(PrimitiveType type) {
645
646 Programs nextProgram = kNoTexture_Program;
647
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000648 GrTexture* texture = fCurrDrawState.fTextures[0];
bsalomon@google.com316f99232011-01-13 21:28:12 +0000649 bool posAsTex =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000650 StagePosAsTexCoordVertexLayoutBit(0) & fGeometrySrc.fVertexLayout;
651
652 if (!VertexUsesStage(0, fGeometrySrc.fVertexLayout)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000653 goto HAVE_NEXT_PROGRAM;
654 }
655
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000656 GrAssert(NULL != texture);
reed@google.comac10a2d2010-12-22 21:39:39 +0000657
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000658 switch (fCurrDrawState.fSamplerStates[0].getSampleMode()) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000659 case GrSamplerState::kRadial_SampleMode:
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000660 GrAssert(!fCurrDrawState.fTextureMatrices[0].hasPerspective());
661 GrAssert(GrTexture::kAlpha_8_PixelConfig != texture->config());
662 if (posAsTex) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000663 nextProgram = kRadialTextureVertCoords_Program;
664 } else {
665 nextProgram = kRadialTextureTexCoords_Program;
666 }
667 break;
668 case GrSamplerState::kSweep_SampleMode:
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000669 GrAssert(!fCurrDrawState.fTextureMatrices[0].hasPerspective());
670 GrAssert(GrTexture::kAlpha_8_PixelConfig != texture->config());
671 if (posAsTex) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000672 nextProgram = kSweepTextureVertCoords_Program;
673 } else {
674 nextProgram = kSweepTextureTexCoords_Program;
675 }
676 break;
677 case GrSamplerState::kRadial2_SampleMode:
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000678 GrAssert(!fCurrDrawState.fTextureMatrices[0].hasPerspective());
679 GrAssert(GrTexture::kAlpha_8_PixelConfig != texture->config());
680 if (posAsTex) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000681 nextProgram = kTwoPointRadialTextureVertCoords_Program;
682 } else {
683 nextProgram = kTwoPointRadialTextureTexCoords_Program;
684 }
685 break;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000686 case GrSamplerState::kNormal_SampleMode:
687 if (GrTexture::kAlpha_8_PixelConfig == texture->config()) {
bsalomon@google.com316f99232011-01-13 21:28:12 +0000688 GrAssert(((GrGLTexture*)texture)->orientation() ==
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000689 GrGLTexture::kTopDown_Orientation);
690 GrAssert(!posAsTex);
691 nextProgram = kText_Program;
reed@google.comac10a2d2010-12-22 21:39:39 +0000692 } else {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000693 bool persp = fCurrDrawState.fTextureMatrices[0].hasPerspective();
694 if (posAsTex) {
bsalomon@google.com316f99232011-01-13 21:28:12 +0000695 nextProgram = persp ? kTextureVertCoordsProj_Program :
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000696 kTextureVertCoords_Program;
697 } else {
bsalomon@google.com316f99232011-01-13 21:28:12 +0000698 nextProgram = persp ? kTextureTexCoordsProj_Program :
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000699 kTextureTexCoords_Program;
700 }
701 // check for case when frag shader can skip the color modulation
702 if (!persp && !(fGeometrySrc.fVertexLayout
703 & kColor_VertexLayoutBit) &&
704 0xffffffff == fCurrDrawState.fColor) {
705 switch (nextProgram) {
706 case kTextureVertCoords_Program:
707 nextProgram = kTextureVertCoordsNoColor_Program;
708 break;
709 case kTextureTexCoords_Program:
710 nextProgram = kTextureTexCoordsNoColor_Program;
711 break;
712 default:
713 GrAssert("Unexpected");
714 break;
715 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000716 }
717 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000718 break;
reed@google.comac10a2d2010-12-22 21:39:39 +0000719 default:
720 GrAssert(!"Unknown samplemode");
721 break;
722 }
723
724HAVE_NEXT_PROGRAM:
725 if (fHWProgram != nextProgram) {
726 GR_GL(UseProgram(fPrograms[nextProgram].fProgramID));
727 fHWProgram = nextProgram;
728#if GR_COLLECT_STATS
729 ++fStats.fProgChngCnt;
730#endif
731 }
732}
733
734bool GrGpuGLShaders::flushGraphicsState(PrimitiveType type) {
reed@google.comac20fb92011-01-12 17:14:53 +0000735
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000736 for (int s = 1; s < kNumStages; ++s) {
737 if (VertexUsesStage(s, fGeometrySrc.fVertexLayout)) {
bsalomon@google.com316f99232011-01-13 21:28:12 +0000738 unimpl("the hard-coded shaders used by this "
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000739 "class only support 1 stage");
740 return false;
741 }
742 }
743
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000744 if (!flushGLStateCommon(type)) {
745 return false;
746 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000747
748 if (fRenderTargetChanged) {
749 // our coords are in pixel space and the GL matrices map to NDC
750 // so if the viewport changed, our matrix is now wrong.
751#if ATTRIBUTE_MATRIX
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000752 fHWDrawState.fViewMatrix.setScale(GR_ScalarMax, GR_ScalarMax);
reed@google.comac10a2d2010-12-22 21:39:39 +0000753#else
754 // we assume all shader matrices may be wrong after viewport changes
755 for (int p = 0; p < kProgramCount; ++p) {
756 // set to illegal matrix
bsalomon@google.com316f99232011-01-13 21:28:12 +0000757 fPrograms[p].fViewMatrix.setScale(GR_ScalarMax, GR_ScalarMax);
reed@google.comac10a2d2010-12-22 21:39:39 +0000758 }
759#endif
760 fRenderTargetChanged = false;
761 }
reed@google.comac20fb92011-01-12 17:14:53 +0000762
reed@google.comac10a2d2010-12-22 21:39:39 +0000763 flushProgram(type);
764
765 if (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) {
766 // invalidate the immediate mode color
reed@google.comac20fb92011-01-12 17:14:53 +0000767 fHWDrawState.fColor = GrColor_ILLEGAL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000768 } else {
769 // if we don't have per-vert colors either set the color attr
770 // or color uniform (depending on which program).
771 if (-1 != fPrograms[fHWProgram].fColorLocation) {
772 GrAssert(kUniform_ColorType == fPrograms[fHWProgram].fColorType);
773 if (fPrograms[fHWProgram].fColor != fCurrDrawState.fColor) {
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(Uniform4fv(fPrograms[fHWProgram].fColorLocation, 1, c));
781 fPrograms[fHWProgram].fColor = fCurrDrawState.fColor;
782 }
reed@google.comac20fb92011-01-12 17:14:53 +0000783 } else if (kAttrib_ColorType == fPrograms[fHWProgram].fColorType &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000784 fHWDrawState.fColor != fCurrDrawState.fColor) {
785 // OpenGL ES only supports the float varities of glVertexAttrib
786 float c[] = {
787 GrColorUnpackR(fCurrDrawState.fColor) / 255.f,
788 GrColorUnpackG(fCurrDrawState.fColor) / 255.f,
789 GrColorUnpackB(fCurrDrawState.fColor) / 255.f,
790 GrColorUnpackA(fCurrDrawState.fColor) / 255.f
791 };
792 GR_GL(VertexAttrib4fv(GR_GL_COL_ATTR_LOCATION, c));
793 fHWDrawState.fColor = fCurrDrawState.fColor;
794 }
795 }
796
797#if ATTRIBUTE_MATRIX
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000798 GrMatrix& currentViewMatrix = fHWDrawState.fViewMatrix;
799 GrMatrix& currentTexMatrix = fHWDrawState.fTextureMatrices[0];
reed@google.comac20fb92011-01-12 17:14:53 +0000800 GrGLTexture::Orientation& orientation = fTextureOrientation;
reed@google.comac10a2d2010-12-22 21:39:39 +0000801#else
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000802 GrMatrix& currentViewMatrix = fPrograms[fHWProgram].fViewMatrix;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000803 GrMatrix& currentTexMatrix = fPrograms[fHWProgram].fTextureMatrices[0];
reed@google.comac20fb92011-01-12 17:14:53 +0000804 GrGLTexture::Orientation& orientation =
reed@google.comac10a2d2010-12-22 21:39:39 +0000805 fPrograms[fHWProgram].fTextureOrientation;
806#endif
807
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000808 if (currentViewMatrix !=
809 fCurrDrawState.fViewMatrix) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000810 flushMatrix(fPrograms[fHWProgram].fMatrixLocation);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000811 currentViewMatrix = fCurrDrawState.fViewMatrix;
reed@google.comac10a2d2010-12-22 21:39:39 +0000812 }
813
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000814 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[0];
reed@google.comac10a2d2010-12-22 21:39:39 +0000815 if (NULL != texture) {
816 if (-1 != fPrograms[fHWProgram].fTexMatrixLocation &&
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000817 (currentTexMatrix != fCurrDrawState.fTextureMatrices[0] ||
reed@google.comac10a2d2010-12-22 21:39:39 +0000818 orientation != texture->orientation())) {
819 flushTexMatrix(fPrograms[fHWProgram].fTexMatrixLocation,
820 texture->orientation());
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000821 currentTexMatrix = fCurrDrawState.fTextureMatrices[0];
reed@google.comac10a2d2010-12-22 21:39:39 +0000822 orientation = texture->orientation();
823 }
824 }
825
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000826 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[0];
reed@google.comac10a2d2010-12-22 21:39:39 +0000827 if (-1 != fPrograms[fHWProgram].fTwoPointParamsLocation &&
828 (fPrograms[fHWProgram].fRadial2CenterX1 != sampler.getRadial2CenterX1() ||
829 fPrograms[fHWProgram].fRadial2Radius0 != sampler.getRadial2Radius0() ||
830 fPrograms[fHWProgram].fRadial2PosRoot != sampler.isRadial2PosRoot())) {
reed@google.comac20fb92011-01-12 17:14:53 +0000831
reed@google.comac10a2d2010-12-22 21:39:39 +0000832 flushTwoPointRadial(fPrograms[fHWProgram].fTwoPointParamsLocation,
833 sampler);
834 fPrograms[fHWProgram].fRadial2CenterX1 = sampler.getRadial2CenterX1();
835 fPrograms[fHWProgram].fRadial2Radius0 = sampler.getRadial2Radius0();
836 fPrograms[fHWProgram].fRadial2PosRoot = sampler.isRadial2PosRoot();
837 }
reed@google.comac20fb92011-01-12 17:14:53 +0000838
reed@google.comac10a2d2010-12-22 21:39:39 +0000839 return true;
840}
841
842void GrGpuGLShaders::setupGeometry(uint32_t startVertex,
843 uint32_t startIndex,
844 uint32_t vertexCount,
845 uint32_t indexCount) {
846
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000847 int newColorOffset;
848 int newTexCoordOffsets[kNumStages];
reed@google.comac20fb92011-01-12 17:14:53 +0000849
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000850 GLsizei newStride = VertexSizeAndOffsetsByStage(fGeometrySrc.fVertexLayout,
bsalomon@google.com316f99232011-01-13 21:28:12 +0000851 newTexCoordOffsets,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000852 &newColorOffset);
853 int oldColorOffset;
854 int oldTexCoordOffsets[kNumStages];
855 GLsizei oldStride = VertexSizeAndOffsetsByStage(fHWGeometryState.fVertexLayout,
bsalomon@google.com316f99232011-01-13 21:28:12 +0000856 oldTexCoordOffsets,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000857 &oldColorOffset);
reed@google.comac20fb92011-01-12 17:14:53 +0000858
reed@google.comac10a2d2010-12-22 21:39:39 +0000859 const GLvoid* posPtr = (GLvoid*)(newStride * startVertex);
reed@google.comac20fb92011-01-12 17:14:53 +0000860
reed@google.comac10a2d2010-12-22 21:39:39 +0000861 if (kBuffer_GeometrySrcType == fGeometrySrc.fVertexSrc) {
862 GrAssert(NULL != fGeometrySrc.fVertexBuffer);
863 GrAssert(!fGeometrySrc.fVertexBuffer->isLocked());
864 if (fHWGeometryState.fVertexBuffer != fGeometrySrc.fVertexBuffer) {
reed@google.comac20fb92011-01-12 17:14:53 +0000865 GrGLVertexBuffer* buf =
reed@google.comac10a2d2010-12-22 21:39:39 +0000866 (GrGLVertexBuffer*)fGeometrySrc.fVertexBuffer;
867 GR_GL(BindBuffer(GL_ARRAY_BUFFER, buf->bufferID()));
868 fHWGeometryState.fVertexBuffer = fGeometrySrc.fVertexBuffer;
869 }
reed@google.comac20fb92011-01-12 17:14:53 +0000870 } else {
reed@google.comac10a2d2010-12-22 21:39:39 +0000871 if (kArray_GeometrySrcType == fGeometrySrc.fVertexSrc) {
reed@google.comac20fb92011-01-12 17:14:53 +0000872 posPtr = (void*)((intptr_t)fGeometrySrc.fVertexArray +
reed@google.comac10a2d2010-12-22 21:39:39 +0000873 (intptr_t)posPtr);
874 } else {
875 GrAssert(kReserved_GeometrySrcType == fGeometrySrc.fVertexSrc);
reed@google.comac20fb92011-01-12 17:14:53 +0000876 posPtr = (void*)((intptr_t)fVertices.get() + (intptr_t)posPtr);
reed@google.comac10a2d2010-12-22 21:39:39 +0000877 }
878 if (NULL != fHWGeometryState.fVertexBuffer) {
879 GR_GL(BindBuffer(GL_ARRAY_BUFFER, 0));
880 fHWGeometryState.fVertexBuffer = NULL;
881 }
882 }
reed@google.comac20fb92011-01-12 17:14:53 +0000883
reed@google.comac10a2d2010-12-22 21:39:39 +0000884 if (kBuffer_GeometrySrcType == fGeometrySrc.fIndexSrc) {
885 GrAssert(NULL != fGeometrySrc.fIndexBuffer);
886 GrAssert(!fGeometrySrc.fIndexBuffer->isLocked());
887 if (fHWGeometryState.fIndexBuffer != fGeometrySrc.fIndexBuffer) {
reed@google.comac20fb92011-01-12 17:14:53 +0000888 GrGLIndexBuffer* buf =
reed@google.comac10a2d2010-12-22 21:39:39 +0000889 (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
890 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf->bufferID()));
891 fHWGeometryState.fIndexBuffer = fGeometrySrc.fIndexBuffer;
892 }
893 } else if (NULL != fHWGeometryState.fIndexBuffer) {
894 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
895 fHWGeometryState.fIndexBuffer = NULL;
896 }
reed@google.comac20fb92011-01-12 17:14:53 +0000897
reed@google.comac10a2d2010-12-22 21:39:39 +0000898 GLenum scalarType;
899 bool texCoordNorm;
900 if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) {
901 scalarType = GrGLTextType;
902 texCoordNorm = GR_GL_TEXT_TEXTURE_NORMALIZED;
903 } else {
904 scalarType = GrGLType;
905 texCoordNorm = false;
906 }
reed@google.comac20fb92011-01-12 17:14:53 +0000907
reed@google.comac10a2d2010-12-22 21:39:39 +0000908 bool baseChange = posPtr != fHWGeometryState.fPositionPtr;
909 bool scalarChange = (GrGLTextType != GrGLType) &&
reed@google.comac20fb92011-01-12 17:14:53 +0000910 (kTextFormat_VertexLayoutBit &
911 (fHWGeometryState.fVertexLayout ^
reed@google.comac10a2d2010-12-22 21:39:39 +0000912 fGeometrySrc.fVertexLayout));
913 bool strideChange = newStride != oldStride;
914 bool posChange = baseChange || scalarChange || strideChange;
reed@google.comac20fb92011-01-12 17:14:53 +0000915
reed@google.comac10a2d2010-12-22 21:39:39 +0000916 if (posChange) {
917 GR_GL(VertexAttribPointer(GR_GL_POS_ATTR_LOCATION, 2, scalarType,
918 false, newStride, posPtr));
919 fHWGeometryState.fPositionPtr = posPtr;
920 }
reed@google.comac20fb92011-01-12 17:14:53 +0000921
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000922 // this class only supports one stage.
923 if (newTexCoordOffsets[0] > 0) {
924 GLvoid* texCoordPtr = (int8_t*)posPtr + newTexCoordOffsets[0];
925 if (oldTexCoordOffsets[0] <= 0) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000926 GR_GL(EnableVertexAttribArray(GR_GL_TEX_ATTR_LOCATION));
927 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000928 if (posChange || newTexCoordOffsets[0] != oldTexCoordOffsets[0]) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000929 GR_GL(VertexAttribPointer(GR_GL_TEX_ATTR_LOCATION, 2, scalarType,
930 texCoordNorm, newStride, texCoordPtr));
931 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000932 } else if (oldTexCoordOffsets[0] > 0) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000933 GR_GL(DisableVertexAttribArray(GR_GL_TEX_ATTR_LOCATION));
934 }
reed@google.comac20fb92011-01-12 17:14:53 +0000935
reed@google.comac10a2d2010-12-22 21:39:39 +0000936 if (newColorOffset > 0) {
937 GLvoid* colorPtr = (int8_t*)posPtr + newColorOffset;
938 if (oldColorOffset <= 0) {
939 GR_GL(EnableVertexAttribArray(GR_GL_COL_ATTR_LOCATION));
940 }
941 if (posChange || newColorOffset != oldColorOffset) {
reed@google.comac20fb92011-01-12 17:14:53 +0000942 GR_GL(VertexAttribPointer(GR_GL_COL_ATTR_LOCATION, 4,
reed@google.comac10a2d2010-12-22 21:39:39 +0000943 GL_UNSIGNED_BYTE,
944 true, newStride, colorPtr));
945 }
946 } else if (oldColorOffset > 0) {
947 GR_GL(DisableVertexAttribArray(GR_GL_COL_ATTR_LOCATION));
948 }
reed@google.comac20fb92011-01-12 17:14:53 +0000949
reed@google.comac10a2d2010-12-22 21:39:39 +0000950 fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout;
951}
952#endif