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