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