qvolray
view src/sdr.c @ 13:17d9dc2edc91
first qt version
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Tue, 10 Apr 2012 06:11:16 +0300 |
parents | b050ce167ff1 |
children |
line source
1 #ifndef NO_SHADERS
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <errno.h>
7 #include <assert.h>
8 #include <GL/glew.h>
10 #if defined(unix) || defined(__unix__)
11 #include <unistd.h>
12 #include <sys/stat.h>
13 #endif /* unix */
15 #include "sdr.h"
17 unsigned int create_vertex_shader(const char *src)
18 {
19 return create_shader(src, GL_VERTEX_SHADER);
20 }
22 unsigned int create_pixel_shader(const char *src)
23 {
24 return create_shader(src, GL_FRAGMENT_SHADER);
25 }
27 unsigned int create_shader(const char *src, unsigned int sdr_type)
28 {
29 unsigned int sdr;
30 int success, info_len;
31 char *info_str = 0;
32 GLenum err;
34 sdr = glCreateShader(sdr_type);
35 assert(glGetError() == GL_NO_ERROR);
36 glShaderSource(sdr, 1, &src, 0);
37 err = glGetError();
38 assert(err == GL_NO_ERROR);
39 glCompileShader(sdr);
40 assert(glGetError() == GL_NO_ERROR);
42 glGetShaderiv(sdr, GL_COMPILE_STATUS, &success);
43 assert(glGetError() == GL_NO_ERROR);
44 glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &info_len);
45 assert(glGetError() == GL_NO_ERROR);
47 if(info_len) {
48 if((info_str = malloc(info_len + 1))) {
49 glGetShaderInfoLog(sdr, info_len, 0, info_str);
50 assert(glGetError() == GL_NO_ERROR);
51 }
52 }
54 if(success) {
55 fprintf(stderr, info_str ? "done: %s\n" : "done\n", info_str);
56 } else {
57 fprintf(stderr, info_str ? "failed: %s\n" : "failed\n", info_str);
58 glDeleteShader(sdr);
59 sdr = 0;
60 }
62 free(info_str);
63 return sdr;
64 }
66 void free_shader(unsigned int sdr)
67 {
68 glDeleteShader(sdr);
69 }
71 unsigned int load_vertex_shader(const char *fname)
72 {
73 return load_shader(fname, GL_VERTEX_SHADER);
74 }
76 unsigned int load_pixel_shader(const char *fname)
77 {
78 return load_shader(fname, GL_FRAGMENT_SHADER);
79 }
81 unsigned int load_shader(const char *fname, unsigned int sdr_type)
82 {
83 #if defined(unix) || defined(__unix__)
84 struct stat st;
85 #endif
86 unsigned int sdr;
87 size_t filesize;
88 FILE *fp;
89 char *src;
91 if(!(fp = fopen(fname, "r"))) {
92 fprintf(stderr, "failed to open shader %s: %s\n", fname, strerror(errno));
93 return 0;
94 }
96 #if defined(unix) || defined(__unix__)
97 fstat(fileno(fp), &st);
98 filesize = st.st_size;
99 #else
100 fseek(fp, 0, SEEK_END);
101 filesize = ftell(fp);
102 fseek(fp, 0, SEEK_SET);
103 #endif /* unix */
105 if(!(src = malloc(filesize + 1))) {
106 fclose(fp);
107 return 0;
108 }
109 fread(src, 1, filesize, fp);
110 src[filesize] = 0;
111 fclose(fp);
113 fprintf(stderr, "compiling %s shader: %s... ", (sdr_type == GL_VERTEX_SHADER ? "vertex" : "pixel"), fname);
114 sdr = create_shader(src, sdr_type);
116 free(src);
117 return sdr;
118 }
121 unsigned int get_vertex_shader(const char *fname)
122 {
123 return get_shader(fname, GL_VERTEX_SHADER);
124 }
126 unsigned int get_pixel_shader(const char *fname)
127 {
128 return get_shader(fname, GL_FRAGMENT_SHADER);
129 }
131 unsigned int get_shader(const char *fname, unsigned int sdr_type)
132 {
133 unsigned int sdr;
135 if(!(sdr = load_shader(fname, sdr_type))) {
136 return 0;
137 }
138 return sdr;
139 }
142 /* ---- gpu programs ---- */
144 unsigned int create_program(void)
145 {
146 unsigned int prog = glCreateProgram();
147 assert(glGetError() == GL_NO_ERROR);
148 return prog;
149 }
151 unsigned int create_program_link(unsigned int vs, unsigned int ps)
152 {
153 unsigned int prog;
155 if(!(prog = create_program())) {
156 return 0;
157 }
159 if(vs) {
160 attach_shader(prog, vs);
161 assert(glGetError() == GL_NO_ERROR);
162 }
163 if(ps) {
164 attach_shader(prog, ps);
165 assert(glGetError() == GL_NO_ERROR);
166 }
168 if(link_program(prog) == -1) {
169 free_program(prog);
170 return 0;
171 }
172 return prog;
173 }
175 unsigned int create_program_load(const char *vfile, const char *pfile)
176 {
177 unsigned int vs = 0, ps = 0;
179 if(vfile && !(vs = get_vertex_shader(vfile))) {
180 return 0;
181 }
182 if(pfile && !(ps = get_pixel_shader(pfile))) {
183 return 0;
184 }
185 return create_program_link(vs, ps);
186 }
188 void free_program(unsigned int sdr)
189 {
190 glDeleteProgram(sdr);
191 }
193 void attach_shader(unsigned int prog, unsigned int sdr)
194 {
195 glAttachShader(prog, sdr);
196 assert(glGetError() == GL_NO_ERROR);
197 }
199 int link_program(unsigned int prog)
200 {
201 int linked, info_len, retval = 0;
202 char *info_str = 0;
204 glLinkProgram(prog);
205 assert(glGetError() == GL_NO_ERROR);
206 glGetProgramiv(prog, GL_LINK_STATUS, &linked);
207 assert(glGetError() == GL_NO_ERROR);
208 glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &info_len);
209 assert(glGetError() == GL_NO_ERROR);
211 if(info_len) {
212 if((info_str = malloc(info_len + 1))) {
213 glGetProgramInfoLog(prog, info_len, 0, info_str);
214 assert(glGetError() == GL_NO_ERROR);
215 }
216 }
218 if(linked) {
219 fprintf(stderr, info_str ? "linking done: %s\n" : "linking done\n", info_str);
220 } else {
221 fprintf(stderr, info_str ? "linking failed: %s\n" : "linking failed\n", info_str);
222 retval = -1;
223 }
225 free(info_str);
226 return retval;
227 }
229 int bind_program(unsigned int prog)
230 {
231 GLenum err;
233 glUseProgram(prog);
234 if(prog && (err = glGetError()) != GL_NO_ERROR) {
235 /* maybe the program is not linked, try linking first */
236 if(err == GL_INVALID_OPERATION) {
237 if(link_program(prog) == -1) {
238 return -1;
239 }
240 glUseProgram(prog);
241 return glGetError() == GL_NO_ERROR ? 0 : -1;
242 }
243 return -1;
244 }
245 return 0;
246 }
248 /* ugly but I'm not going to write the same bloody code over and over */
249 #define BEGIN_UNIFORM_CODE \
250 int loc, curr_prog; \
251 glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); \
252 if((unsigned int)curr_prog != prog && bind_program(prog) == -1) { \
253 return -1; \
254 } \
255 if((loc = glGetUniformLocation(prog, name)) != -1)
257 #define END_UNIFORM_CODE \
258 if((unsigned int)curr_prog != prog) { \
259 bind_program(curr_prog); \
260 } \
261 return loc == -1 ? -1 : 0
263 int set_uniform_int(unsigned int prog, const char *name, int val)
264 {
265 BEGIN_UNIFORM_CODE {
266 glUniform1i(loc, val);
267 }
268 END_UNIFORM_CODE;
269 }
271 int set_uniform_float(unsigned int prog, const char *name, float val)
272 {
273 BEGIN_UNIFORM_CODE {
274 glUniform1f(loc, val);
275 }
276 END_UNIFORM_CODE;
277 }
279 int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z)
280 {
281 BEGIN_UNIFORM_CODE {
282 glUniform3f(loc, x, y, z);
283 }
284 END_UNIFORM_CODE;
285 }
287 int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w)
288 {
289 BEGIN_UNIFORM_CODE {
290 glUniform4f(loc, x, y, z, w);
291 }
292 END_UNIFORM_CODE;
293 }
295 int set_uniform_matrix4(unsigned int prog, const char *name, float *mat)
296 {
297 BEGIN_UNIFORM_CODE {
298 glUniformMatrix4fv(loc, 1, GL_FALSE, mat);
299 }
300 END_UNIFORM_CODE;
301 }
303 int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat)
304 {
305 BEGIN_UNIFORM_CODE {
306 glUniformMatrix4fv(loc, 1, GL_TRUE, mat);
307 }
308 END_UNIFORM_CODE;
309 }
311 int get_attrib_loc(unsigned int prog, const char *name)
312 {
313 int loc, curr_prog;
315 glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog);
316 if((unsigned int)curr_prog != prog && bind_program(prog) == -1) {
317 return -1;
318 }
320 loc = glGetAttribLocation(prog, (char*)name);
322 if((unsigned int)curr_prog != prog) {
323 bind_program(curr_prog);
324 }
325 return loc;
326 }
328 void set_attrib_float3(int attr_loc, float x, float y, float z)
329 {
330 glVertexAttrib3f(attr_loc, x, y, z);
331 }
333 #endif /* !NO_SHADERS */