blob: 2ace2ad240306a3fb8c7a50837c0d6722253b7d0 [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) {
517 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
579 glVertexAttrib4fv(GR_GL_MAT_ATTR_LOCATION+0, mt+0);
580 glVertexAttrib4fv(GR_GL_MAT_ATTR_LOCATION+1, mt+3);
581 glVertexAttrib4fv(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
618 glVertexAttrib4fv(GR_GL_TEXMAT_ATTR_LOCATION+0, mt+0);
619 glVertexAttrib4fv(GR_GL_TEXMAT_ATTR_LOCATION+1, mt+3);
620 glVertexAttrib4fv(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];
649 bool posAsTex =
650 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()) {
688 GrAssert(((GrGLTexture*)texture)->orientation() ==
689 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) {
695 nextProgram = persp ? kTextureVertCoordsProj_Program :
696 kTextureVertCoords_Program;
697 } else {
698 nextProgram = persp ? kTextureTexCoordsProj_Program :
699 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)) {
738 unimpl("the hard-coded shaders used by this "
739 "class only support 1 stage");
740 return false;
741 }
742 }
743
reed@google.comac10a2d2010-12-22 21:39:39 +0000744 flushGLStateCommon(type);
745
746 if (fRenderTargetChanged) {
747 // our coords are in pixel space and the GL matrices map to NDC
748 // so if the viewport changed, our matrix is now wrong.
749#if ATTRIBUTE_MATRIX
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000750 fHWDrawState.fViewMatrix.setScale(GR_ScalarMax, GR_ScalarMax);
reed@google.comac10a2d2010-12-22 21:39:39 +0000751#else
752 // we assume all shader matrices may be wrong after viewport changes
753 for (int p = 0; p < kProgramCount; ++p) {
754 // set to illegal matrix
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000755 fPrograms[p].fViewMatrix.setScale(GR_ScalarMax, GR_ScalarMax);
reed@google.comac10a2d2010-12-22 21:39:39 +0000756 }
757#endif
758 fRenderTargetChanged = false;
759 }
reed@google.comac20fb92011-01-12 17:14:53 +0000760
reed@google.comac10a2d2010-12-22 21:39:39 +0000761 flushProgram(type);
762
763 if (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) {
764 // invalidate the immediate mode color
reed@google.comac20fb92011-01-12 17:14:53 +0000765 fHWDrawState.fColor = GrColor_ILLEGAL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000766 } else {
767 // if we don't have per-vert colors either set the color attr
768 // or color uniform (depending on which program).
769 if (-1 != fPrograms[fHWProgram].fColorLocation) {
770 GrAssert(kUniform_ColorType == fPrograms[fHWProgram].fColorType);
771 if (fPrograms[fHWProgram].fColor != fCurrDrawState.fColor) {
772 float c[] = {
773 GrColorUnpackR(fCurrDrawState.fColor) / 255.f,
774 GrColorUnpackG(fCurrDrawState.fColor) / 255.f,
775 GrColorUnpackB(fCurrDrawState.fColor) / 255.f,
776 GrColorUnpackA(fCurrDrawState.fColor) / 255.f
777 };
778 GR_GL(Uniform4fv(fPrograms[fHWProgram].fColorLocation, 1, c));
779 fPrograms[fHWProgram].fColor = fCurrDrawState.fColor;
780 }
reed@google.comac20fb92011-01-12 17:14:53 +0000781 } else if (kAttrib_ColorType == fPrograms[fHWProgram].fColorType &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000782 fHWDrawState.fColor != fCurrDrawState.fColor) {
783 // OpenGL ES only supports the float varities of glVertexAttrib
784 float c[] = {
785 GrColorUnpackR(fCurrDrawState.fColor) / 255.f,
786 GrColorUnpackG(fCurrDrawState.fColor) / 255.f,
787 GrColorUnpackB(fCurrDrawState.fColor) / 255.f,
788 GrColorUnpackA(fCurrDrawState.fColor) / 255.f
789 };
790 GR_GL(VertexAttrib4fv(GR_GL_COL_ATTR_LOCATION, c));
791 fHWDrawState.fColor = fCurrDrawState.fColor;
792 }
793 }
794
795#if ATTRIBUTE_MATRIX
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000796 GrMatrix& currentViewMatrix = fHWDrawState.fViewMatrix;
797 GrMatrix& currentTexMatrix = fHWDrawState.fTextureMatrices[0];
reed@google.comac20fb92011-01-12 17:14:53 +0000798 GrGLTexture::Orientation& orientation = fTextureOrientation;
reed@google.comac10a2d2010-12-22 21:39:39 +0000799#else
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000800 GrMatrix& currentViewMatrix = fPrograms[fHWProgram].fViewMatrix;
801 GrMatrix& currentTexMatrix = fPrograms[fHWProgram].fTextureMatrices[0];
reed@google.comac20fb92011-01-12 17:14:53 +0000802 GrGLTexture::Orientation& orientation =
reed@google.comac10a2d2010-12-22 21:39:39 +0000803 fPrograms[fHWProgram].fTextureOrientation;
804#endif
805
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000806 if (currentViewMatrix !=
807 fCurrDrawState.fViewMatrix) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000808 flushMatrix(fPrograms[fHWProgram].fMatrixLocation);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000809 currentViewMatrix = fCurrDrawState.fViewMatrix;
reed@google.comac10a2d2010-12-22 21:39:39 +0000810 }
811
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000812 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[0];
reed@google.comac10a2d2010-12-22 21:39:39 +0000813 if (NULL != texture) {
814 if (-1 != fPrograms[fHWProgram].fTexMatrixLocation &&
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000815 (currentTexMatrix != fCurrDrawState.fTextureMatrices[0] ||
reed@google.comac10a2d2010-12-22 21:39:39 +0000816 orientation != texture->orientation())) {
817 flushTexMatrix(fPrograms[fHWProgram].fTexMatrixLocation,
818 texture->orientation());
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000819 currentTexMatrix = fCurrDrawState.fTextureMatrices[0];
reed@google.comac10a2d2010-12-22 21:39:39 +0000820 orientation = texture->orientation();
821 }
822 }
823
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000824 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[0];
reed@google.comac10a2d2010-12-22 21:39:39 +0000825 if (-1 != fPrograms[fHWProgram].fTwoPointParamsLocation &&
826 (fPrograms[fHWProgram].fRadial2CenterX1 != sampler.getRadial2CenterX1() ||
827 fPrograms[fHWProgram].fRadial2Radius0 != sampler.getRadial2Radius0() ||
828 fPrograms[fHWProgram].fRadial2PosRoot != sampler.isRadial2PosRoot())) {
reed@google.comac20fb92011-01-12 17:14:53 +0000829
reed@google.comac10a2d2010-12-22 21:39:39 +0000830 flushTwoPointRadial(fPrograms[fHWProgram].fTwoPointParamsLocation,
831 sampler);
832 fPrograms[fHWProgram].fRadial2CenterX1 = sampler.getRadial2CenterX1();
833 fPrograms[fHWProgram].fRadial2Radius0 = sampler.getRadial2Radius0();
834 fPrograms[fHWProgram].fRadial2PosRoot = sampler.isRadial2PosRoot();
835 }
reed@google.comac20fb92011-01-12 17:14:53 +0000836
reed@google.comac10a2d2010-12-22 21:39:39 +0000837 return true;
838}
839
840void GrGpuGLShaders::setupGeometry(uint32_t startVertex,
841 uint32_t startIndex,
842 uint32_t vertexCount,
843 uint32_t indexCount) {
844
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000845 int newColorOffset;
846 int newTexCoordOffsets[kNumStages];
reed@google.comac20fb92011-01-12 17:14:53 +0000847
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000848 GLsizei newStride = VertexSizeAndOffsetsByStage(fGeometrySrc.fVertexLayout,
849 newTexCoordOffsets,
850 &newColorOffset);
851 int oldColorOffset;
852 int oldTexCoordOffsets[kNumStages];
853 GLsizei oldStride = VertexSizeAndOffsetsByStage(fHWGeometryState.fVertexLayout,
854 oldTexCoordOffsets,
855 &oldColorOffset);
reed@google.comac20fb92011-01-12 17:14:53 +0000856
reed@google.comac10a2d2010-12-22 21:39:39 +0000857 const GLvoid* posPtr = (GLvoid*)(newStride * startVertex);
reed@google.comac20fb92011-01-12 17:14:53 +0000858
reed@google.comac10a2d2010-12-22 21:39:39 +0000859 if (kBuffer_GeometrySrcType == fGeometrySrc.fVertexSrc) {
860 GrAssert(NULL != fGeometrySrc.fVertexBuffer);
861 GrAssert(!fGeometrySrc.fVertexBuffer->isLocked());
862 if (fHWGeometryState.fVertexBuffer != fGeometrySrc.fVertexBuffer) {
reed@google.comac20fb92011-01-12 17:14:53 +0000863 GrGLVertexBuffer* buf =
reed@google.comac10a2d2010-12-22 21:39:39 +0000864 (GrGLVertexBuffer*)fGeometrySrc.fVertexBuffer;
865 GR_GL(BindBuffer(GL_ARRAY_BUFFER, buf->bufferID()));
866 fHWGeometryState.fVertexBuffer = fGeometrySrc.fVertexBuffer;
867 }
reed@google.comac20fb92011-01-12 17:14:53 +0000868 } else {
reed@google.comac10a2d2010-12-22 21:39:39 +0000869 if (kArray_GeometrySrcType == fGeometrySrc.fVertexSrc) {
reed@google.comac20fb92011-01-12 17:14:53 +0000870 posPtr = (void*)((intptr_t)fGeometrySrc.fVertexArray +
reed@google.comac10a2d2010-12-22 21:39:39 +0000871 (intptr_t)posPtr);
872 } else {
873 GrAssert(kReserved_GeometrySrcType == fGeometrySrc.fVertexSrc);
reed@google.comac20fb92011-01-12 17:14:53 +0000874 posPtr = (void*)((intptr_t)fVertices.get() + (intptr_t)posPtr);
reed@google.comac10a2d2010-12-22 21:39:39 +0000875 }
876 if (NULL != fHWGeometryState.fVertexBuffer) {
877 GR_GL(BindBuffer(GL_ARRAY_BUFFER, 0));
878 fHWGeometryState.fVertexBuffer = NULL;
879 }
880 }
reed@google.comac20fb92011-01-12 17:14:53 +0000881
reed@google.comac10a2d2010-12-22 21:39:39 +0000882 if (kBuffer_GeometrySrcType == fGeometrySrc.fIndexSrc) {
883 GrAssert(NULL != fGeometrySrc.fIndexBuffer);
884 GrAssert(!fGeometrySrc.fIndexBuffer->isLocked());
885 if (fHWGeometryState.fIndexBuffer != fGeometrySrc.fIndexBuffer) {
reed@google.comac20fb92011-01-12 17:14:53 +0000886 GrGLIndexBuffer* buf =
reed@google.comac10a2d2010-12-22 21:39:39 +0000887 (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
888 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf->bufferID()));
889 fHWGeometryState.fIndexBuffer = fGeometrySrc.fIndexBuffer;
890 }
891 } else if (NULL != fHWGeometryState.fIndexBuffer) {
892 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
893 fHWGeometryState.fIndexBuffer = NULL;
894 }
reed@google.comac20fb92011-01-12 17:14:53 +0000895
reed@google.comac10a2d2010-12-22 21:39:39 +0000896 GLenum scalarType;
897 bool texCoordNorm;
898 if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) {
899 scalarType = GrGLTextType;
900 texCoordNorm = GR_GL_TEXT_TEXTURE_NORMALIZED;
901 } else {
902 scalarType = GrGLType;
903 texCoordNorm = false;
904 }
reed@google.comac20fb92011-01-12 17:14:53 +0000905
reed@google.comac10a2d2010-12-22 21:39:39 +0000906 bool baseChange = posPtr != fHWGeometryState.fPositionPtr;
907 bool scalarChange = (GrGLTextType != GrGLType) &&
reed@google.comac20fb92011-01-12 17:14:53 +0000908 (kTextFormat_VertexLayoutBit &
909 (fHWGeometryState.fVertexLayout ^
reed@google.comac10a2d2010-12-22 21:39:39 +0000910 fGeometrySrc.fVertexLayout));
911 bool strideChange = newStride != oldStride;
912 bool posChange = baseChange || scalarChange || strideChange;
reed@google.comac20fb92011-01-12 17:14:53 +0000913
reed@google.comac10a2d2010-12-22 21:39:39 +0000914 if (posChange) {
915 GR_GL(VertexAttribPointer(GR_GL_POS_ATTR_LOCATION, 2, scalarType,
916 false, newStride, posPtr));
917 fHWGeometryState.fPositionPtr = posPtr;
918 }
reed@google.comac20fb92011-01-12 17:14:53 +0000919
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000920 // this class only supports one stage.
921 if (newTexCoordOffsets[0] > 0) {
922 GLvoid* texCoordPtr = (int8_t*)posPtr + newTexCoordOffsets[0];
923 if (oldTexCoordOffsets[0] <= 0) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000924 GR_GL(EnableVertexAttribArray(GR_GL_TEX_ATTR_LOCATION));
925 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000926 if (posChange || newTexCoordOffsets[0] != oldTexCoordOffsets[0]) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000927 GR_GL(VertexAttribPointer(GR_GL_TEX_ATTR_LOCATION, 2, scalarType,
928 texCoordNorm, newStride, texCoordPtr));
929 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000930 } else if (oldTexCoordOffsets[0] > 0) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000931 GR_GL(DisableVertexAttribArray(GR_GL_TEX_ATTR_LOCATION));
932 }
reed@google.comac20fb92011-01-12 17:14:53 +0000933
reed@google.comac10a2d2010-12-22 21:39:39 +0000934 if (newColorOffset > 0) {
935 GLvoid* colorPtr = (int8_t*)posPtr + newColorOffset;
936 if (oldColorOffset <= 0) {
937 GR_GL(EnableVertexAttribArray(GR_GL_COL_ATTR_LOCATION));
938 }
939 if (posChange || newColorOffset != oldColorOffset) {
reed@google.comac20fb92011-01-12 17:14:53 +0000940 GR_GL(VertexAttribPointer(GR_GL_COL_ATTR_LOCATION, 4,
reed@google.comac10a2d2010-12-22 21:39:39 +0000941 GL_UNSIGNED_BYTE,
942 true, newStride, colorPtr));
943 }
944 } else if (oldColorOffset > 0) {
945 GR_GL(DisableVertexAttribArray(GR_GL_COL_ATTR_LOCATION));
946 }
reed@google.comac20fb92011-01-12 17:14:53 +0000947
reed@google.comac10a2d2010-12-22 21:39:39 +0000948 fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout;
949}
950#endif