blob: 8f4bfaf00b6d2b18e4245f963ca128e4ee6b5e49 [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"
82 "attribute vec2 aTexture;\n"
83 "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
136 "uniform " GR_PRECISION " float uParams[6];\n"
137 // 0 is t^2 term of quadratic
138 // 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
159 "uniform " GR_PRECISION " float uParams[6];\n"
160 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
200
201 "}\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",
254
255 // 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"
261 "uniform float uParams[6];\n"
262 "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;
279 GrGpuGLShaders::ColorType fColorType;
280} gProgramLoadData[] = {
281 // kTextureVertCoords_Program
282 {0, 0, true, false, false, GrGpuGLShaders::kAttrib_ColorType },
283 // kTextureVertCoordsProj_Program
284 {0, 1, true, false, false, GrGpuGLShaders::kAttrib_ColorType },
285 // kTextureTexCoords_Program
286 {1, 0, true, true, false, GrGpuGLShaders::kAttrib_ColorType },
287 // kTextureTexCoordsProj_Program
288 {1, 1, true, true, false, GrGpuGLShaders::kAttrib_ColorType },
289 // 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
300 {0, 5, true, false, false, GrGpuGLShaders::kAttrib_ColorType },
301 // kRadialTextureTexCoords_Program
302 {1, 5, true, true, false, GrGpuGLShaders::kAttrib_ColorType },
303 // kSweepTextureVertCoords_Program
304 {0, 6, true, false, false, GrGpuGLShaders::kAttrib_ColorType },
305 // 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
329 GLint compiled;
330 GR_GL(ShaderSource(shader, 1, &src, NULL));
331 GR_GL(CompileShader(shader));
332 GR_GL(GetShaderiv(shader, GL_COMPILE_STATUS, &compiled));
333
334 if (!compiled) {
335 GLint infoLen;
336 GR_GL(GetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen));
337 GrAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
338 if (infoLen > 0) {
339 GR_GL(GetShaderInfoLog(shader, infoLen+1, NULL, (char*)log.get()));
340 GrPrintf((char*)log.get());
341 }
342 GrAssert(!"Shader compilation failed!");
343 GR_GL(DeleteShader(shader));
344 return 0;
345 }
346 return shader;
347}
348
349bool GrGpuGLShaders::createProgram(GLuint vshader, GLuint fshader,
350 bool hasTexMatrix,
351 bool hasTexCoords,
352 GrGpuGLShaders::ColorType colorType,
353 bool twoPointRadial,
354 ProgramData* program) {
355 program->fProgramID = GR_GL(CreateProgram());
356 program->fVShaderID = vshader;
357 program->fFShaderID = fshader;
358
359 GrAssert(0 != program->fProgramID);
360
361 GR_GL(AttachShader(program->fProgramID, vshader));
362 GR_GL(AttachShader(program->fProgramID, fshader));
363
364 GR_GL(BindAttribLocation(program->fProgramID,
365 GR_GL_POS_ATTR_LOCATION,
366 "aPosition"));
367 if (hasTexCoords) {
368 GR_GL(BindAttribLocation(program->fProgramID,
369 GR_GL_TEX_ATTR_LOCATION,
370 "aTexture"));
371 }
372#if ATTRIBUTE_MATRIX
373 if (hasTexMatrix) {
374 GR_GL(BindAttribLocation(program->fProgramID,
375 GR_GL_TEXMAT_ATTR_LOCATION,
376 "texM"));
377 // set to something arbitrary to signal to flush that program
378 // uses the texture matrix.
379 program->fTexMatrixLocation = 1000;
380 }
381#endif
382 if (colorType == kAttrib_ColorType) {
383 GR_GL(BindAttribLocation(program->fProgramID,
384 GR_GL_COL_ATTR_LOCATION,
385 "aColor"));
386 }
387#if ATTRIBUTE_MATRIX
388 GR_GL(BindAttribLocation(program->fProgramID,
389 GR_GL_MAT_ATTR_LOCATION,
390 "viewM"));
391#endif
392
393 GR_GL(LinkProgram(program->fProgramID));
394
395 GLint linked;
396 GR_GL(GetProgramiv(program->fProgramID, GL_LINK_STATUS, &linked));
397 if (!linked) {
398 GLint infoLen;
399 GR_GL(GetProgramiv(program->fProgramID, GL_INFO_LOG_LENGTH, &infoLen));
400 GrAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
401 if (infoLen > 0) {
402 GR_GL(GetProgramInfoLog(program->fProgramID,
403 infoLen+1,
404 NULL,
405 (char*)log.get()));
406 GrPrintf((char*)log.get());
407 }
408 GrAssert(!"Error linking program");
409 GR_GL(DeleteProgram(program->fProgramID));
410 program->fProgramID = 0;
411 return false;
412 }
413 program->fColorType = colorType;
414
415#if !ATTRIBUTE_MATRIX
416 program->fMatrixLocation =
417 GR_GL(GetUniformLocation(program->fProgramID, "viewM"));
418 program->fTexMatrixLocation =
419 GR_GL(GetUniformLocation(program->fProgramID, "texM"));
420#endif
421 program->fColorLocation =
422 GR_GL(GetUniformLocation(program->fProgramID, "uColor"));
423 program->fTwoPointParamsLocation =
424 GR_GL(GetUniformLocation(program->fProgramID, "uParams"));
425
426 GLint samplerLocation =
427 GR_GL(GetUniformLocation(program->fProgramID, "sTexture"));
428
429#if !ATTRIBUTE_MATRIX
430 if (-1 == program->fMatrixLocation) {
431 GrAssert(!"Cannot find matrix uniform in program");
432 GR_GL(DeleteProgram(program->fProgramID));
433 program->fProgramID = 0;
434 return false;
435 }
436#endif
437
438 bool hasTexture = hasTexCoords || hasTexMatrix;
439
440 if (-1 == samplerLocation && hasTexture) {
441 GrAssert(!"Expected to find texture sampler");
442 GR_GL(DeleteProgram(program->fProgramID));
443 program->fProgramID = 0;
444 return false;
445 } else if (-1 != samplerLocation && !hasTexture) {
446 GrAssert(!"unexpectedly found texture sampler");
447 }
448#if !ATTRIBUTE_MATRIX
449 if (-1 == program->fTexMatrixLocation && hasTexMatrix) {
450 GrAssert(!"Expected to find texture matrix");
451 GR_GL(DeleteProgram(program->fProgramID));
452 program->fProgramID = 0;
453 return false;
454 } else if (-1 != program->fTexMatrixLocation && !hasTexMatrix) {
455 GrAssert(!"unexpectedly found texture matrix");
456 }
457#endif
458
459 if (-1 == program->fColorLocation &&
460 (kUniform_ColorType == colorType)) {
461 GR_GL(DeleteProgram(program->fProgramID));
462 program->fProgramID = 0;
463 return false;
464 } else if (-1 != program->fColorLocation &&
465 (kUniform_ColorType != colorType)) {
466 GrAssert(!"Unexpectedly found color uniform");
467 }
468
469 if (twoPointRadial) {
470 if (-1 == program->fTwoPointParamsLocation) {
471 GrAssert(!"Didn't find expected uniform for 2pt radial gradient");
472 GR_GL(DeleteProgram(program->fProgramID));
473 program->fProgramID = 0;
474 return false;
475 }
476 } else {
477 GrAssert(-1 == program->fTwoPointParamsLocation);
478 }
479
480 GR_GL(UseProgram(program->fProgramID));
481 if (-1 != samplerLocation) {
482 GR_GL(Uniform1i(samplerLocation, 0));
483 }
484
485 return true;
486}
487
488GrGpuGLShaders::GrGpuGLShaders() {
489
490 resetContextHelper();
491
492 GLuint vshadIDs[GR_ARRAY_COUNT(gvshad)];
493 for (size_t s = 0; s < GR_ARRAY_COUNT(gvshad); ++s) {
494 vshadIDs[s] = loadShader(GL_VERTEX_SHADER, gvshad[s]);
495 }
496
497 GLuint fshadIDs[GR_ARRAY_COUNT(gfshad)];
498 for (size_t s = 0; s < GR_ARRAY_COUNT(gfshad); ++s) {
499 fshadIDs[s] = loadShader(GL_FRAGMENT_SHADER, gfshad[s]);
500 }
501
502 GR_STATIC_ASSERT(kProgramCount == GR_ARRAY_COUNT(gProgramLoadData));
503 for (int p = 0; p < kProgramCount; ++p) {
504 GR_DEBUGCODE(bool result = )
505 createProgram(vshadIDs[gProgramLoadData[p].fVShaderIdx],
506 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);
513
514 for (int m = 0; m < kMatrixModeCount; ++m) {
515 fPrograms[p].fMatrixModeCache[m].setScale(GR_ScalarMax,
516 GR_ScalarMax); // illegal
517 };
518 fPrograms[p].fColor = GrColor_ILLEGAL;
519 fPrograms[p].fTextureOrientation = (GrGLTexture::Orientation)-1; // illegal
520
521 // these aren't strictly invalid, just really unlikely.
522 fPrograms[p].fRadial2CenterX1 = GR_ScalarMin;
523 fPrograms[p].fRadial2Radius0 = GR_ScalarMin;
524 fPrograms[p].fRadial2PosRoot = true; // arbitrary
525 }
526}
527
528GrGpuGLShaders::~GrGpuGLShaders() {
529 // shaders get deleted once for each program that uses them, do we care?
530 // probably not
531 for (int i = 0; i < kProgramCount; ++i) {
532 GR_GL(DeleteProgram(fPrograms[i].fProgramID));
533 GR_GL(DeleteShader(fPrograms[i].fVShaderID));
534 GR_GL(DeleteShader(fPrograms[i].fFShaderID));
535 }
536}
537
538void GrGpuGLShaders::resetContext() {
539 INHERITED::resetContext();
540 resetContextHelper();
541}
542
543void GrGpuGLShaders::resetContextHelper() {
544 fHWProgram = (Programs)-1;
545 fTextureOrientation = (GrGLTexture::Orientation)-1; // illegal
546
547 fHWGeometryState.fVertexLayout = 0;
548 fHWGeometryState.fPositionPtr = (void*) ~0;
549 GR_GL(DisableVertexAttribArray(GR_GL_COL_ATTR_LOCATION));
550 GR_GL(DisableVertexAttribArray(GR_GL_TEX_ATTR_LOCATION));
551 GR_GL(EnableVertexAttribArray(GR_GL_POS_ATTR_LOCATION));
552}
553
554
555void GrGpuGLShaders::flushMatrix(GLint location) {
556 GrAssert(NULL != fCurrDrawState.fRenderTarget);
557 GrMatrix m (
558 GrIntToScalar(2) / fCurrDrawState.fRenderTarget->width(), 0, -GR_Scalar1,
559 0,-GrIntToScalar(2) / fCurrDrawState.fRenderTarget->height(), GR_Scalar1,
560 0, 0, GrMatrix::I()[8]);
561 m.setConcat(m, fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode]);
562
563 // ES doesn't allow you to pass true to the transpose param,
564 // so do our own transpose
565 GrScalar mt[] = {
566 m[GrMatrix::kScaleX],
567 m[GrMatrix::kSkewY],
568 m[GrMatrix::kPersp0],
569 m[GrMatrix::kSkewX],
570 m[GrMatrix::kScaleY],
571 m[GrMatrix::kPersp1],
572 m[GrMatrix::kTransX],
573 m[GrMatrix::kTransY],
574 m[GrMatrix::kPersp2]
575 };
576#if ATTRIBUTE_MATRIX
577 glVertexAttrib4fv(GR_GL_MAT_ATTR_LOCATION+0, mt+0);
578 glVertexAttrib4fv(GR_GL_MAT_ATTR_LOCATION+1, mt+3);
579 glVertexAttrib4fv(GR_GL_MAT_ATTR_LOCATION+2, mt+6);
580#else
581 GR_GL(UniformMatrix3fv(location,1,false,mt));
582#endif
583}
584
585void GrGpuGLShaders::flushTexMatrix(GLint location,
586 GrGLTexture::Orientation orientation) {
587 GrMatrix* m;
588 GrMatrix temp;
589 if (GrGLTexture::kBottomUp_Orientation == orientation) {
590 temp.setAll(
591 GR_Scalar1, 0, 0,
592 0, -GR_Scalar1, GR_Scalar1,
593 0, 0, GrMatrix::I()[8]
594 );
595 temp.preConcat(fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode]);
596 m = &temp;
597 } else {
598 GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
599 m = &fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode];
600 }
601
602 // ES doesn't allow you to pass true to the transpose param,
603 // so do our own transpose
604 GrScalar mt[] = {
605 (*m)[GrMatrix::kScaleX],
606 (*m)[GrMatrix::kSkewY],
607 (*m)[GrMatrix::kPersp0],
608 (*m)[GrMatrix::kSkewX],
609 (*m)[GrMatrix::kScaleY],
610 (*m)[GrMatrix::kPersp1],
611 (*m)[GrMatrix::kTransX],
612 (*m)[GrMatrix::kTransY],
613 (*m)[GrMatrix::kPersp2]
614 };
615#if ATTRIBUTE_MATRIX
616 glVertexAttrib4fv(GR_GL_TEXMAT_ATTR_LOCATION+0, mt+0);
617 glVertexAttrib4fv(GR_GL_TEXMAT_ATTR_LOCATION+1, mt+3);
618 glVertexAttrib4fv(GR_GL_TEXMAT_ATTR_LOCATION+2, mt+6);
619#else
620 GR_GL(UniformMatrix3fv(location,1,false,mt));
621#endif
622}
623
624void GrGpuGLShaders::flushTwoPointRadial(GLint paramsLocation,
625 const GrSamplerState& state) {
626 GrScalar centerX1 = state.getRadial2CenterX1();
627 GrScalar radius0 = state.getRadial2Radius0();
628
629 GrScalar a = GrMul(centerX1, centerX1) - GR_Scalar1;
630
631 float unis[6] = {
632 GrScalarToFloat(a),
633 1 / (2.f * unis[0]),
634 GrScalarToFloat(centerX1),
635 GrScalarToFloat(radius0),
636 GrScalarToFloat(GrMul(radius0, radius0)),
637 state.isRadial2PosRoot() ? 1.f : -1.f
638 };
639 GR_GL(Uniform1fv(paramsLocation, 6, unis));
640}
641
642void GrGpuGLShaders::flushProgram(PrimitiveType type) {
643
644 Programs nextProgram = kNoTexture_Program;
645
646 if (!VertexHasTexCoords(fGeometrySrc.fVertexLayout)) {
647 goto HAVE_NEXT_PROGRAM;
648 }
649
650 GrAssert(fCurrDrawState.fTexture);
651
652 switch (fCurrDrawState.fSamplerState.getSampleMode()) {
653 case GrSamplerState::kRadial_SampleMode:
654 GrAssert(!fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode].hasPerspective());
655 if (fGeometrySrc.fVertexLayout & kPositionAsTexCoord_VertexLayoutBit) {
656 nextProgram = kRadialTextureVertCoords_Program;
657 } else {
658 nextProgram = kRadialTextureTexCoords_Program;
659 }
660 break;
661 case GrSamplerState::kSweep_SampleMode:
662 GrAssert(!fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode].hasPerspective());
663 if (fGeometrySrc.fVertexLayout & kPositionAsTexCoord_VertexLayoutBit) {
664 nextProgram = kSweepTextureVertCoords_Program;
665 } else {
666 nextProgram = kSweepTextureTexCoords_Program;
667 }
668 break;
669 case GrSamplerState::kRadial2_SampleMode:
670 GrAssert(!fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode].hasPerspective());
671 if (fGeometrySrc.fVertexLayout & kPositionAsTexCoord_VertexLayoutBit) {
672 nextProgram = kTwoPointRadialTextureVertCoords_Program;
673 } else {
674 nextProgram = kTwoPointRadialTextureTexCoords_Program;
675 }
676 break;
677 case GrSamplerState::kAlphaMod_SampleMode:
678 GrAssert(((GrGLTexture*)fCurrDrawState.fTexture)->orientation() ==
679 GrGLTexture::kTopDown_Orientation);
680 (((GrGLTexture*)fCurrDrawState.fTexture)->uploadFormat() == GL_ALPHA);
681
682 nextProgram = kText_Program;
683 break;
684 case GrSamplerState::kNormal_SampleMode: {
685 GR_DEBUGCODE(GrGLTexture* tex = (GrGLTexture*)fCurrDrawState.fTexture;)
686 GrAssert(tex);
687
688 bool persp = fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode].hasPerspective();
689
690 if (fGeometrySrc.fVertexLayout & kPositionAsTexCoord_VertexLayoutBit) {
691 nextProgram = persp ? kTextureVertCoordsProj_Program :
692 kTextureVertCoords_Program;
693 } else {
694 nextProgram = persp ? kTextureTexCoordsProj_Program :
695 kTextureTexCoords_Program;
696 }
697 // check for case when frag shader can skip the color modulation
698 if (!persp && !(fGeometrySrc.fVertexLayout
699 & kColor_VertexLayoutBit) &&
700 0xffffffff == fCurrDrawState.fColor) {
701 switch (nextProgram) {
702 case kTextureVertCoords_Program:
703 nextProgram = kTextureVertCoordsNoColor_Program;
704 break;
705 case kTextureTexCoords_Program:
706 nextProgram = kTextureTexCoordsNoColor_Program;
707 break;
708 default:
709 GrAssert("Unexpected");
710 break;
711 }
712 }
713 } break;
714 default:
715 GrAssert(!"Unknown samplemode");
716 break;
717 }
718
719HAVE_NEXT_PROGRAM:
720 if (fHWProgram != nextProgram) {
721 GR_GL(UseProgram(fPrograms[nextProgram].fProgramID));
722 fHWProgram = nextProgram;
723#if GR_COLLECT_STATS
724 ++fStats.fProgChngCnt;
725#endif
726 }
727}
728
729bool GrGpuGLShaders::flushGraphicsState(PrimitiveType type) {
730
731 flushGLStateCommon(type);
732
733 if (fRenderTargetChanged) {
734 // our coords are in pixel space and the GL matrices map to NDC
735 // so if the viewport changed, our matrix is now wrong.
736#if ATTRIBUTE_MATRIX
737 fHWDrawState.fMatrixModeCache[kModelView_MatrixMode].setScale(GR_ScalarMax,
738 GR_ScalarMax);
739#else
740 // we assume all shader matrices may be wrong after viewport changes
741 for (int p = 0; p < kProgramCount; ++p) {
742 // set to illegal matrix
743 fPrograms[p].fMatrixModeCache[kModelView_MatrixMode].setScale(GR_ScalarMax,
744 GR_ScalarMax);
745 }
746#endif
747 fRenderTargetChanged = false;
748 }
749
750 flushProgram(type);
751
752 if (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) {
753 // invalidate the immediate mode color
754 fHWDrawState.fColor = GrColor_ILLEGAL;
755 } else {
756 // if we don't have per-vert colors either set the color attr
757 // or color uniform (depending on which program).
758 if (-1 != fPrograms[fHWProgram].fColorLocation) {
759 GrAssert(kUniform_ColorType == fPrograms[fHWProgram].fColorType);
760 if (fPrograms[fHWProgram].fColor != fCurrDrawState.fColor) {
761 float c[] = {
762 GrColorUnpackR(fCurrDrawState.fColor) / 255.f,
763 GrColorUnpackG(fCurrDrawState.fColor) / 255.f,
764 GrColorUnpackB(fCurrDrawState.fColor) / 255.f,
765 GrColorUnpackA(fCurrDrawState.fColor) / 255.f
766 };
767 GR_GL(Uniform4fv(fPrograms[fHWProgram].fColorLocation, 1, c));
768 fPrograms[fHWProgram].fColor = fCurrDrawState.fColor;
769 }
770 } else if (kAttrib_ColorType == fPrograms[fHWProgram].fColorType &&
771 fHWDrawState.fColor != fCurrDrawState.fColor) {
772 // OpenGL ES only supports the float varities of glVertexAttrib
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(VertexAttrib4fv(GR_GL_COL_ATTR_LOCATION, c));
780 fHWDrawState.fColor = fCurrDrawState.fColor;
781 }
782 }
783
784#if ATTRIBUTE_MATRIX
785 GrMatrix* currentMats = fHWDrawState.fMatrixModeCache;
786 GrGLTexture::Orientation& orientation = fTextureOrientation;
787#else
788 GrMatrix* currentMats = fPrograms[fHWProgram].fMatrixModeCache;
789 GrGLTexture::Orientation& orientation =
790 fPrograms[fHWProgram].fTextureOrientation;
791#endif
792
793 if (currentMats[kModelView_MatrixMode] !=
794 fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode]) {
795 flushMatrix(fPrograms[fHWProgram].fMatrixLocation);
796 currentMats[kModelView_MatrixMode] =
797 fCurrDrawState.fMatrixModeCache[kModelView_MatrixMode];
798 }
799
800 GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTexture;
801 if (NULL != texture) {
802 if (-1 != fPrograms[fHWProgram].fTexMatrixLocation &&
803 (currentMats[kTexture_MatrixMode] !=
804 fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode] ||
805 orientation != texture->orientation())) {
806 flushTexMatrix(fPrograms[fHWProgram].fTexMatrixLocation,
807 texture->orientation());
808 currentMats[kTexture_MatrixMode] =
809 fCurrDrawState.fMatrixModeCache[kTexture_MatrixMode];
810 orientation = texture->orientation();
811 }
812 }
813
814 const GrSamplerState& sampler = fCurrDrawState.fSamplerState;
815 if (-1 != fPrograms[fHWProgram].fTwoPointParamsLocation &&
816 (fPrograms[fHWProgram].fRadial2CenterX1 != sampler.getRadial2CenterX1() ||
817 fPrograms[fHWProgram].fRadial2Radius0 != sampler.getRadial2Radius0() ||
818 fPrograms[fHWProgram].fRadial2PosRoot != sampler.isRadial2PosRoot())) {
819
820 flushTwoPointRadial(fPrograms[fHWProgram].fTwoPointParamsLocation,
821 sampler);
822 fPrograms[fHWProgram].fRadial2CenterX1 = sampler.getRadial2CenterX1();
823 fPrograms[fHWProgram].fRadial2Radius0 = sampler.getRadial2Radius0();
824 fPrograms[fHWProgram].fRadial2PosRoot = sampler.isRadial2PosRoot();
825 }
826
827 return true;
828}
829
830void GrGpuGLShaders::setupGeometry(uint32_t startVertex,
831 uint32_t startIndex,
832 uint32_t vertexCount,
833 uint32_t indexCount) {
834
835 int newColorOffset, newTexCoordOffset;
836
837 GLsizei newStride = VertexSizeAndOffsets(fGeometrySrc.fVertexLayout,
838 &newTexCoordOffset,
839 &newColorOffset);
840 int oldColorOffset, oldTexCoordOffset;
841 GLsizei oldStride = VertexSizeAndOffsets(fHWGeometryState.fVertexLayout,
842 &oldTexCoordOffset,
843 &oldColorOffset);
844
845 const GLvoid* posPtr = (GLvoid*)(newStride * startVertex);
846
847 if (kBuffer_GeometrySrcType == fGeometrySrc.fVertexSrc) {
848 GrAssert(NULL != fGeometrySrc.fVertexBuffer);
849 GrAssert(!fGeometrySrc.fVertexBuffer->isLocked());
850 if (fHWGeometryState.fVertexBuffer != fGeometrySrc.fVertexBuffer) {
851 GrGLVertexBuffer* buf =
852 (GrGLVertexBuffer*)fGeometrySrc.fVertexBuffer;
853 GR_GL(BindBuffer(GL_ARRAY_BUFFER, buf->bufferID()));
854 fHWGeometryState.fVertexBuffer = fGeometrySrc.fVertexBuffer;
855 }
856 } else {
857 if (kArray_GeometrySrcType == fGeometrySrc.fVertexSrc) {
858 posPtr = (void*)((intptr_t)fGeometrySrc.fVertexArray +
859 (intptr_t)posPtr);
860 } else {
861 GrAssert(kReserved_GeometrySrcType == fGeometrySrc.fVertexSrc);
862 posPtr = (void*)((intptr_t)fVertices.get() + (intptr_t)posPtr);
863 }
864 if (NULL != fHWGeometryState.fVertexBuffer) {
865 GR_GL(BindBuffer(GL_ARRAY_BUFFER, 0));
866 fHWGeometryState.fVertexBuffer = NULL;
867 }
868 }
869
870 if (kBuffer_GeometrySrcType == fGeometrySrc.fIndexSrc) {
871 GrAssert(NULL != fGeometrySrc.fIndexBuffer);
872 GrAssert(!fGeometrySrc.fIndexBuffer->isLocked());
873 if (fHWGeometryState.fIndexBuffer != fGeometrySrc.fIndexBuffer) {
874 GrGLIndexBuffer* buf =
875 (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
876 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf->bufferID()));
877 fHWGeometryState.fIndexBuffer = fGeometrySrc.fIndexBuffer;
878 }
879 } else if (NULL != fHWGeometryState.fIndexBuffer) {
880 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
881 fHWGeometryState.fIndexBuffer = NULL;
882 }
883
884 GLenum scalarType;
885 bool texCoordNorm;
886 if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) {
887 scalarType = GrGLTextType;
888 texCoordNorm = GR_GL_TEXT_TEXTURE_NORMALIZED;
889 } else {
890 scalarType = GrGLType;
891 texCoordNorm = false;
892 }
893
894 bool baseChange = posPtr != fHWGeometryState.fPositionPtr;
895 bool scalarChange = (GrGLTextType != GrGLType) &&
896 (kTextFormat_VertexLayoutBit &
897 (fHWGeometryState.fVertexLayout ^
898 fGeometrySrc.fVertexLayout));
899 bool strideChange = newStride != oldStride;
900 bool posChange = baseChange || scalarChange || strideChange;
901
902 if (posChange) {
903 GR_GL(VertexAttribPointer(GR_GL_POS_ATTR_LOCATION, 2, scalarType,
904 false, newStride, posPtr));
905 fHWGeometryState.fPositionPtr = posPtr;
906 }
907
908 if (newTexCoordOffset > 0) {
909 GLvoid* texCoordPtr = (int8_t*)posPtr + newTexCoordOffset;
910 if (oldTexCoordOffset <= 0) {
911 GR_GL(EnableVertexAttribArray(GR_GL_TEX_ATTR_LOCATION));
912 }
913 if (posChange || newTexCoordOffset != oldTexCoordOffset) {
914 GR_GL(VertexAttribPointer(GR_GL_TEX_ATTR_LOCATION, 2, scalarType,
915 texCoordNorm, newStride, texCoordPtr));
916 }
917 } else if (oldTexCoordOffset > 0) {
918 GR_GL(DisableVertexAttribArray(GR_GL_TEX_ATTR_LOCATION));
919 }
920
921 if (newColorOffset > 0) {
922 GLvoid* colorPtr = (int8_t*)posPtr + newColorOffset;
923 if (oldColorOffset <= 0) {
924 GR_GL(EnableVertexAttribArray(GR_GL_COL_ATTR_LOCATION));
925 }
926 if (posChange || newColorOffset != oldColorOffset) {
927 GR_GL(VertexAttribPointer(GR_GL_COL_ATTR_LOCATION, 4,
928 GL_UNSIGNED_BYTE,
929 true, newStride, colorPtr));
930 }
931 } else if (oldColorOffset > 0) {
932 GR_GL(DisableVertexAttribArray(GR_GL_COL_ATTR_LOCATION));
933 }
934
935 fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout;
936}
937#endif