Merge branch 'radeon-texrewrite-clean' into mesa_7_7_branch
[mesa.git] / progs / util / shaderutil.c
1 /**
2 * Utilities for OpenGL shading language
3 *
4 * Brian Paul
5 * 9 April 2008
6 */
7
8
9 #include <assert.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <GL/glew.h>
14 #include <GL/glut.h>
15 #include "shaderutil.h"
16
17 /** time to compile previous shader */
18 static GLdouble CompileTime = 0.0;
19
20 /** time to linke previous program */
21 static GLdouble LinkTime = 0.0;
22
23
24 GLboolean
25 ShadersSupported(void)
26 {
27 const char *version = (const char *) glGetString(GL_VERSION);
28 if (version[0] == '2' && version[1] == '.') {
29 return GL_TRUE;
30 }
31 else if (glutExtensionSupported("GL_ARB_vertex_shader")
32 && glutExtensionSupported("GL_ARB_fragment_shader")
33 && glutExtensionSupported("GL_ARB_shader_objects")) {
34 fprintf(stderr, "Warning: Trying ARB GLSL instead of OpenGL 2.x. This may not work.\n");
35 return GL_TRUE;
36 }
37 fprintf(stderr, "Sorry, GLSL not supported with this OpenGL.\n");
38 return GL_FALSE;
39 }
40
41
42 GLuint
43 CompileShaderText(GLenum shaderType, const char *text)
44 {
45 GLuint shader;
46 GLint stat;
47 GLdouble t0, t1;
48
49 shader = glCreateShader(shaderType);
50 glShaderSource(shader, 1, (const GLchar **) &text, NULL);
51
52 t0 = glutGet(GLUT_ELAPSED_TIME) * 0.001;
53 glCompileShader(shader);
54 t1 = glutGet(GLUT_ELAPSED_TIME) * 0.001;
55
56 CompileTime = t1 - t0;
57
58 glGetShaderiv(shader, GL_COMPILE_STATUS, &stat);
59 if (!stat) {
60 GLchar log[1000];
61 GLsizei len;
62 glGetShaderInfoLog(shader, 1000, &len, log);
63 fprintf(stderr, "Error: problem compiling shader: %s\n", log);
64 exit(1);
65 }
66 else {
67 /*printf("Shader compiled OK\n");*/
68 }
69 return shader;
70 }
71
72
73 /**
74 * Read a shader from a file.
75 */
76 GLuint
77 CompileShaderFile(GLenum shaderType, const char *filename)
78 {
79 const int max = 100*1000;
80 int n;
81 char *buffer = (char*) malloc(max);
82 GLuint shader;
83 FILE *f;
84
85 f = fopen(filename, "r");
86 if (!f) {
87 fprintf(stderr, "Unable to open shader file %s\n", filename);
88 free(buffer);
89 return 0;
90 }
91
92 n = fread(buffer, 1, max, f);
93 /*printf("read %d bytes from shader file %s\n", n, filename);*/
94 if (n > 0) {
95 buffer[n] = 0;
96 shader = CompileShaderText(shaderType, buffer);
97 }
98 else {
99 fclose(f);
100 free(buffer);
101 return 0;
102 }
103
104 fclose(f);
105 free(buffer);
106
107 return shader;
108 }
109
110
111 GLuint
112 LinkShaders(GLuint vertShader, GLuint fragShader)
113 {
114 GLuint program = glCreateProgram();
115 GLdouble t0, t1;
116
117 assert(vertShader || fragShader);
118
119 if (fragShader)
120 glAttachShader(program, fragShader);
121 if (vertShader)
122 glAttachShader(program, vertShader);
123
124 t0 = glutGet(GLUT_ELAPSED_TIME) * 0.001;
125 glLinkProgram(program);
126 t1 = glutGet(GLUT_ELAPSED_TIME) * 0.001;
127
128 LinkTime = t1 - t0;
129
130 /* check link */
131 {
132 GLint stat;
133 glGetProgramiv(program, GL_LINK_STATUS, &stat);
134 if (!stat) {
135 GLchar log[1000];
136 GLsizei len;
137 glGetProgramInfoLog(program, 1000, &len, log);
138 fprintf(stderr, "Shader link error:\n%s\n", log);
139 return 0;
140 }
141 }
142
143 return program;
144 }
145
146
147 GLboolean
148 ValidateShaderProgram(GLuint program)
149 {
150 GLint stat;
151 glValidateProgramARB(program);
152 glGetProgramiv(program, GL_VALIDATE_STATUS, &stat);
153
154 if (!stat) {
155 GLchar log[1000];
156 GLsizei len;
157 glGetProgramInfoLog(program, 1000, &len, log);
158 fprintf(stderr, "Program validation error:\n%s\n", log);
159 return 0;
160 }
161
162 return (GLboolean) stat;
163 }
164
165
166 GLdouble
167 GetShaderCompileTime(void)
168 {
169 return CompileTime;
170 }
171
172
173 GLdouble
174 GetShaderLinkTime(void)
175 {
176 return LinkTime;
177 }
178
179
180 void
181 SetUniformValues(GLuint program, struct uniform_info uniforms[])
182 {
183 GLuint i;
184
185 for (i = 0; uniforms[i].name; i++) {
186 uniforms[i].location
187 = glGetUniformLocation(program, uniforms[i].name);
188
189 switch (uniforms[i].type) {
190 case GL_INT:
191 case GL_SAMPLER_1D:
192 case GL_SAMPLER_2D:
193 case GL_SAMPLER_3D:
194 case GL_SAMPLER_CUBE:
195 case GL_SAMPLER_2D_RECT_ARB:
196 assert(uniforms[i].value[0] >= 0.0F);
197 glUniform1i(uniforms[i].location,
198 (GLint) uniforms[i].value[0]);
199 break;
200 case GL_FLOAT:
201 glUniform1fv(uniforms[i].location, 1, uniforms[i].value);
202 break;
203 case GL_FLOAT_VEC2:
204 glUniform2fv(uniforms[i].location, 1, uniforms[i].value);
205 break;
206 case GL_FLOAT_VEC3:
207 glUniform3fv(uniforms[i].location, 1, uniforms[i].value);
208 break;
209 case GL_FLOAT_VEC4:
210 glUniform4fv(uniforms[i].location, 1, uniforms[i].value);
211 break;
212 default:
213 if (strncmp(uniforms[i].name, "gl_", 3) == 0) {
214 /* built-in uniform: ignore */
215 }
216 else {
217 fprintf(stderr,
218 "Unexpected uniform data type in SetUniformValues\n");
219 abort();
220 }
221 }
222 }
223 }
224
225
226 /** Get list of uniforms used in the program */
227 GLuint
228 GetUniforms(GLuint program, struct uniform_info uniforms[])
229 {
230 GLint n, max, i;
231
232 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &n);
233 glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max);
234
235 for (i = 0; i < n; i++) {
236 GLint size, len;
237 GLenum type;
238 char name[100];
239
240 glGetActiveUniform(program, i, 100, &len, &size, &type, name);
241
242 uniforms[i].name = strdup(name);
243 uniforms[i].size = size;
244 uniforms[i].type = type;
245 uniforms[i].location = glGetUniformLocation(program, name);
246 }
247
248 uniforms[i].name = NULL; /* end of list */
249
250 return n;
251 }
252
253
254 void
255 PrintUniforms(const struct uniform_info uniforms[])
256 {
257 GLint i;
258
259 printf("Uniforms:\n");
260
261 for (i = 0; uniforms[i].name; i++) {
262 printf(" %d: %s size=%d type=0x%x loc=%d value=%g, %g, %g, %g\n",
263 i,
264 uniforms[i].name,
265 uniforms[i].size,
266 uniforms[i].type,
267 uniforms[i].location,
268 uniforms[i].value[0],
269 uniforms[i].value[1],
270 uniforms[i].value[2],
271 uniforms[i].value[3]);
272 }
273 }
274
275
276 /** Get list of attribs used in the program */
277 GLuint
278 GetAttribs(GLuint program, struct attrib_info attribs[])
279 {
280 GLint n, max, i;
281
282 glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &n);
283 glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max);
284
285 for (i = 0; i < n; i++) {
286 GLint size, len;
287 GLenum type;
288 char name[100];
289
290 glGetActiveAttrib(program, i, 100, &len, &size, &type, name);
291
292 attribs[i].name = strdup(name);
293 attribs[i].size = size;
294 attribs[i].type = type;
295 attribs[i].location = glGetAttribLocation(program, name);
296 }
297
298 attribs[i].name = NULL; /* end of list */
299
300 return n;
301 }
302
303
304 void
305 PrintAttribs(const struct attrib_info attribs[])
306 {
307 GLint i;
308
309 printf("Attribs:\n");
310
311 for (i = 0; attribs[i].name; i++) {
312 printf(" %d: %s size=%d type=0x%x loc=%d\n",
313 i,
314 attribs[i].name,
315 attribs[i].size,
316 attribs[i].type,
317 attribs[i].location);
318 }
319 }