13b68d90e0bcd697597fcdad7514ba13d71da0eb
[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 <GL/glew.h>
13 #include <GL/glut.h>
14 #include "shaderutil.h"
15
16
17 static void
18 Init(void)
19 {
20 static GLboolean firstCall = GL_TRUE;
21 if (firstCall) {
22 firstCall = GL_FALSE;
23 }
24 }
25
26
27 GLboolean
28 ShadersSupported(void)
29 {
30 const char *version = (const char *) glGetString(GL_VERSION);
31 if (version[0] == '2' && version[1] == '.') {
32 return GL_TRUE;
33 }
34 else if (glutExtensionSupported("GL_ARB_vertex_shader")
35 && glutExtensionSupported("GL_ARB_fragment_shader")
36 && glutExtensionSupported("GL_ARB_shader_objects")) {
37 fprintf(stderr, "Warning: Trying ARB GLSL instead of OpenGL 2.x. This may not work.\n");
38 return GL_TRUE;
39 }
40 return GL_TRUE;
41 }
42
43
44 GLuint
45 CompileShaderText(GLenum shaderType, const char *text)
46 {
47 GLuint shader;
48 GLint stat;
49
50 Init();
51
52 shader = glCreateShader(shaderType);
53 glShaderSource(shader, 1, (const GLchar **) &text, NULL);
54 glCompileShader(shader);
55 glGetShaderiv(shader, GL_COMPILE_STATUS, &stat);
56 if (!stat) {
57 GLchar log[1000];
58 GLsizei len;
59 glGetShaderInfoLog(shader, 1000, &len, log);
60 fprintf(stderr, "Error: problem compiling shader: %s\n", log);
61 exit(1);
62 }
63 else {
64 /*printf("Shader compiled OK\n");*/
65 }
66 return shader;
67 }
68
69
70 /**
71 * Read a shader from a file.
72 */
73 GLuint
74 CompileShaderFile(GLenum shaderType, const char *filename)
75 {
76 const int max = 100*1000;
77 int n;
78 char *buffer = (char*) malloc(max);
79 GLuint shader;
80 FILE *f;
81
82 Init();
83
84
85 f = fopen(filename, "r");
86 if (!f) {
87 fprintf(stderr, "Unable to open shader file %s\n", filename);
88 return 0;
89 }
90
91 n = fread(buffer, 1, max, f);
92 /*printf("read %d bytes from shader file %s\n", n, filename);*/
93 if (n > 0) {
94 buffer[n] = 0;
95 shader = CompileShaderText(shaderType, buffer);
96 }
97 else {
98 return 0;
99 }
100
101 fclose(f);
102 free(buffer);
103
104 return shader;
105 }
106
107
108 GLuint
109 LinkShaders(GLuint vertShader, GLuint fragShader)
110 {
111 GLuint program = glCreateProgram();
112
113 assert(vertShader || fragShader);
114
115 if (fragShader)
116 glAttachShader(program, fragShader);
117 if (vertShader)
118 glAttachShader(program, vertShader);
119 glLinkProgram(program);
120
121 /* check link */
122 {
123 GLint stat;
124 glGetProgramiv(program, GL_LINK_STATUS, &stat);
125 if (!stat) {
126 GLchar log[1000];
127 GLsizei len;
128 glGetProgramInfoLog(program, 1000, &len, log);
129 fprintf(stderr, "Shader link error:\n%s\n", log);
130 return 0;
131 }
132 }
133
134 return program;
135 }
136
137
138 void
139 InitUniforms(GLuint program, struct uniform_info uniforms[])
140 {
141 GLuint i;
142
143 for (i = 0; uniforms[i].name; i++) {
144 uniforms[i].location
145 = glGetUniformLocation(program, uniforms[i].name);
146
147 printf("Uniform %s location: %d\n", uniforms[i].name,
148 uniforms[i].location);
149
150 switch (uniforms[i].size) {
151 case 1:
152 if (uniforms[i].type == GL_INT)
153 glUniform1i(uniforms[i].location,
154 (GLint) uniforms[i].value[0]);
155 else
156 glUniform1fv(uniforms[i].location, 1, uniforms[i].value);
157 break;
158 case 2:
159 glUniform2fv(uniforms[i].location, 1, uniforms[i].value);
160 break;
161 case 3:
162 glUniform3fv(uniforms[i].location, 1, uniforms[i].value);
163 break;
164 case 4:
165 glUniform4fv(uniforms[i].location, 1, uniforms[i].value);
166 break;
167 default:
168 abort();
169 }
170 }
171 }