Merge branch 'asm-shader-rework-1'
[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 return GL_TRUE;
38 }
39
40
41 GLuint
42 CompileShaderText(GLenum shaderType, const char *text)
43 {
44 GLuint shader;
45 GLint stat;
46 GLdouble t0, t1;
47
48 shader = glCreateShader(shaderType);
49 glShaderSource(shader, 1, (const GLchar **) &text, NULL);
50
51 t0 = glutGet(GLUT_ELAPSED_TIME) * 0.001;
52 glCompileShader(shader);
53 t1 = glutGet(GLUT_ELAPSED_TIME) * 0.001;
54
55 CompileTime = t1 - t0;
56
57 glGetShaderiv(shader, GL_COMPILE_STATUS, &stat);
58 if (!stat) {
59 GLchar log[1000];
60 GLsizei len;
61 glGetShaderInfoLog(shader, 1000, &len, log);
62 fprintf(stderr, "Error: problem compiling shader: %s\n", log);
63 exit(1);
64 }
65 else {
66 /*printf("Shader compiled OK\n");*/
67 }
68 return shader;
69 }
70
71
72 /**
73 * Read a shader from a file.
74 */
75 GLuint
76 CompileShaderFile(GLenum shaderType, const char *filename)
77 {
78 const int max = 100*1000;
79 int n;
80 char *buffer = (char*) malloc(max);
81 GLuint shader;
82 FILE *f;
83
84 f = fopen(filename, "r");
85 if (!f) {
86 fprintf(stderr, "Unable to open shader file %s\n", filename);
87 return 0;
88 }
89
90 n = fread(buffer, 1, max, f);
91 /*printf("read %d bytes from shader file %s\n", n, filename);*/
92 if (n > 0) {
93 buffer[n] = 0;
94 shader = CompileShaderText(shaderType, buffer);
95 }
96 else {
97 return 0;
98 }
99
100 fclose(f);
101 free(buffer);
102
103 return shader;
104 }
105
106
107 GLuint
108 LinkShaders(GLuint vertShader, GLuint fragShader)
109 {
110 GLuint program = glCreateProgram();
111 GLdouble t0, t1;
112
113 assert(vertShader || fragShader);
114
115 if (fragShader)
116 glAttachShader(program, fragShader);
117 if (vertShader)
118 glAttachShader(program, vertShader);
119
120 t0 = glutGet(GLUT_ELAPSED_TIME) * 0.001;
121 glLinkProgram(program);
122 t1 = glutGet(GLUT_ELAPSED_TIME) * 0.001;
123
124 LinkTime = t1 - t0;
125
126 /* check link */
127 {
128 GLint stat;
129 glGetProgramiv(program, GL_LINK_STATUS, &stat);
130 if (!stat) {
131 GLchar log[1000];
132 GLsizei len;
133 glGetProgramInfoLog(program, 1000, &len, log);
134 fprintf(stderr, "Shader link error:\n%s\n", log);
135 return 0;
136 }
137 }
138
139 return program;
140 }
141
142
143 GLdouble
144 GetShaderCompileTime(void)
145 {
146 return CompileTime;
147 }
148
149
150 GLdouble
151 GetShaderLinkTime(void)
152 {
153 return LinkTime;
154 }
155
156
157 void
158 SetUniformValues(GLuint program, struct uniform_info uniforms[])
159 {
160 GLuint i;
161
162 for (i = 0; uniforms[i].name; i++) {
163 uniforms[i].location
164 = glGetUniformLocation(program, uniforms[i].name);
165
166 switch (uniforms[i].type) {
167 case GL_INT:
168 case GL_SAMPLER_1D:
169 case GL_SAMPLER_2D:
170 case GL_SAMPLER_3D:
171 case GL_SAMPLER_CUBE:
172 case GL_SAMPLER_2D_RECT_ARB:
173 glUniform1i(uniforms[i].location,
174 (GLint) uniforms[i].value[0]);
175 break;
176 case GL_FLOAT:
177 glUniform1fv(uniforms[i].location, 1, uniforms[i].value);
178 break;
179 case GL_FLOAT_VEC2:
180 glUniform2fv(uniforms[i].location, 1, uniforms[i].value);
181 break;
182 case GL_FLOAT_VEC3:
183 glUniform3fv(uniforms[i].location, 1, uniforms[i].value);
184 break;
185 case GL_FLOAT_VEC4:
186 glUniform4fv(uniforms[i].location, 1, uniforms[i].value);
187 break;
188 default:
189 if (strncmp(uniforms[i].name, "gl_", 3) == 0) {
190 /* built-in uniform: ignore */
191 }
192 else {
193 fprintf(stderr,
194 "Unexpected uniform data type in SetUniformValues\n");
195 abort();
196 }
197 }
198 }
199 }
200
201
202 /** Get list of uniforms used in the program */
203 GLuint
204 GetUniforms(GLuint program, struct uniform_info uniforms[])
205 {
206 GLint n, max, i;
207
208 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &n);
209 glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max);
210
211 for (i = 0; i < n; i++) {
212 GLint size, len;
213 GLenum type;
214 char name[100];
215
216 glGetActiveUniform(program, i, 100, &len, &size, &type, name);
217
218 uniforms[i].name = strdup(name);
219 uniforms[i].size = size;
220 uniforms[i].type = type;
221 uniforms[i].location = glGetUniformLocation(program, name);
222 }
223
224 uniforms[i].name = NULL; /* end of list */
225
226 return n;
227 }
228
229
230 void
231 PrintUniforms(const struct uniform_info uniforms[])
232 {
233 GLint i;
234
235 printf("Uniforms:\n");
236
237 for (i = 0; uniforms[i].name; i++) {
238 printf(" %d: %s size=%d type=0x%x loc=%d value=%g, %g, %g, %g\n",
239 i,
240 uniforms[i].name,
241 uniforms[i].size,
242 uniforms[i].type,
243 uniforms[i].location,
244 uniforms[i].value[0],
245 uniforms[i].value[1],
246 uniforms[i].value[2],
247 uniforms[i].value[3]);
248 }
249 }
250
251
252 /** Get list of attribs used in the program */
253 GLuint
254 GetAttribs(GLuint program, struct attrib_info attribs[])
255 {
256 GLint n, max, i;
257
258 glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &n);
259 glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max);
260
261 for (i = 0; i < n; i++) {
262 GLint size, len;
263 GLenum type;
264 char name[100];
265
266 glGetActiveAttrib(program, i, 100, &len, &size, &type, name);
267
268 attribs[i].name = strdup(name);
269 attribs[i].size = size;
270 attribs[i].type = type;
271 attribs[i].location = glGetAttribLocation(program, name);
272 }
273
274 attribs[i].name = NULL; /* end of list */
275
276 return n;
277 }
278
279
280 void
281 PrintAttribs(const struct attrib_info attribs[])
282 {
283 GLint i;
284
285 printf("Attribs:\n");
286
287 for (i = 0; attribs[i].name; i++) {
288 printf(" %d: %s size=%d type=0x%x loc=%d\n",
289 i,
290 attribs[i].name,
291 attribs[i].size,
292 attribs[i].type,
293 attribs[i].location);
294 }
295 }