glviewvol

view src/sdr.c @ 4:04330eb80b36

lots of stuff
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 29 Dec 2014 05:41:36 +0200
parents
children 773f89037a35
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <stdarg.h>
6 #include <assert.h>
7 #include <GL/glew.h>
9 #if defined(unix) || defined(__unix__)
10 #include <unistd.h>
11 #include <sys/stat.h>
12 #endif /* unix */
14 #include "sdr.h"
16 static const char *sdrtypestr(unsigned int sdrtype);
18 unsigned int create_vertex_shader(const char *src)
19 {
20 return create_shader(src, GL_VERTEX_SHADER);
21 }
23 unsigned int create_pixel_shader(const char *src)
24 {
25 return create_shader(src, GL_FRAGMENT_SHADER);
26 }
28 unsigned int create_tessctl_shader(const char *src)
29 {
30 #ifdef GL_TESS_CONTROL_SHADER
31 return create_shader(src, GL_TESS_CONTROL_SHADER);
32 #else
33 return 0;
34 #endif
35 }
37 unsigned int create_tesseval_shader(const char *src)
38 {
39 #ifdef GL_TESS_EVALUATION_SHADER
40 return create_shader(src, GL_TESS_EVALUATION_SHADER);
41 #else
42 return 0;
43 #endif
44 }
46 unsigned int create_geometry_shader(const char *src)
47 {
48 #ifdef GL_GEOMETRY_SHADER
49 return create_shader(src, GL_GEOMETRY_SHADER);
50 #else
51 return 0;
52 #endif
53 }
55 unsigned int create_shader(const char *src, unsigned int sdr_type)
56 {
57 unsigned int sdr;
58 int success, info_len;
59 char *info_str = 0;
60 GLenum err;
62 sdr = glCreateShader(sdr_type);
63 assert(glGetError() == GL_NO_ERROR);
64 glShaderSource(sdr, 1, &src, 0);
65 err = glGetError();
66 assert(err == GL_NO_ERROR);
67 glCompileShader(sdr);
68 assert(glGetError() == GL_NO_ERROR);
70 glGetShaderiv(sdr, GL_COMPILE_STATUS, &success);
71 assert(glGetError() == GL_NO_ERROR);
72 glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &info_len);
73 assert(glGetError() == GL_NO_ERROR);
75 if(info_len) {
76 if((info_str = malloc(info_len + 1))) {
77 glGetShaderInfoLog(sdr, info_len, 0, info_str);
78 assert(glGetError() == GL_NO_ERROR);
79 info_str[info_len] = 0;
80 }
81 }
83 if(success) {
84 fprintf(stderr, info_str ? "done: %s\n" : "done\n", info_str);
85 } else {
86 fprintf(stderr, info_str ? "failed: %s\n" : "failed\n", info_str);
87 glDeleteShader(sdr);
88 sdr = 0;
89 }
91 free(info_str);
92 return sdr;
93 }
95 void free_shader(unsigned int sdr)
96 {
97 glDeleteShader(sdr);
98 }
100 unsigned int load_vertex_shader(const char *fname)
101 {
102 return load_shader(fname, GL_VERTEX_SHADER);
103 }
105 unsigned int load_pixel_shader(const char *fname)
106 {
107 return load_shader(fname, GL_FRAGMENT_SHADER);
108 }
110 unsigned int load_tessctl_shader(const char *fname)
111 {
112 #ifdef GL_TESS_CONTROL_SHADER
113 return load_shader(fname, GL_TESS_CONTROL_SHADER);
114 #else
115 return 0;
116 #endif
117 }
119 unsigned int load_tesseval_shader(const char *fname)
120 {
121 #ifdef GL_TESS_EVALUATION_SHADER
122 return load_shader(fname, GL_TESS_EVALUATION_SHADER);
123 #else
124 return 0;
125 #endif
126 }
128 unsigned int load_geometry_shader(const char *fname)
129 {
130 #ifdef GL_GEOMETRY_SHADER
131 return load_shader(fname, GL_GEOMETRY_SHADER);
132 #else
133 return 0;
134 #endif
135 }
137 unsigned int load_shader(const char *fname, unsigned int sdr_type)
138 {
139 #if defined(unix) || defined(__unix__)
140 struct stat st;
141 #endif
142 unsigned int sdr;
143 size_t filesize;
144 FILE *fp;
145 char *src;
147 if(!(fp = fopen(fname, "rb"))) {
148 fprintf(stderr, "failed to open shader %s: %s\n", fname, strerror(errno));
149 return 0;
150 }
152 #if defined(unix) || defined(__unix__)
153 fstat(fileno(fp), &st);
154 filesize = st.st_size;
155 #else
156 fseek(fp, 0, SEEK_END);
157 filesize = ftell(fp);
158 fseek(fp, 0, SEEK_SET);
159 #endif /* unix */
161 if(!(src = malloc(filesize + 1))) {
162 fclose(fp);
163 return 0;
164 }
165 fread(src, 1, filesize, fp);
166 src[filesize] = 0;
167 fclose(fp);
169 fprintf(stderr, "compiling %s shader: %s... ", sdrtypestr(sdr_type), fname);
170 sdr = create_shader(src, sdr_type);
172 free(src);
173 return sdr;
174 }
177 unsigned int get_vertex_shader(const char *fname)
178 {
179 return get_shader(fname, GL_VERTEX_SHADER);
180 }
182 unsigned int get_pixel_shader(const char *fname)
183 {
184 return get_shader(fname, GL_FRAGMENT_SHADER);
185 }
187 unsigned int get_tessctl_shader(const char *fname)
188 {
189 #ifdef GL_TESS_CONTROL_SHADER
190 return get_shader(fname, GL_TESS_CONTROL_SHADER);
191 #else
192 return 0;
193 #endif
194 }
196 unsigned int get_tesseval_shader(const char *fname)
197 {
198 #ifdef GL_TESS_EVALUATION_SHADER
199 return get_shader(fname, GL_TESS_EVALUATION_SHADER);
200 #else
201 return 0;
202 #endif
203 }
205 unsigned int get_geometry_shader(const char *fname)
206 {
207 #ifdef GL_GEOMETRY_SHADER
208 return get_shader(fname, GL_GEOMETRY_SHADER);
209 #else
210 return 0;
211 #endif
212 }
214 unsigned int get_shader(const char *fname, unsigned int sdr_type)
215 {
216 unsigned int sdr;
217 if(!(sdr = load_shader(fname, sdr_type))) {
218 return 0;
219 }
220 return sdr;
221 }
224 /* ---- gpu programs ---- */
226 unsigned int create_program(void)
227 {
228 unsigned int prog = glCreateProgram();
229 assert(glGetError() == GL_NO_ERROR);
230 return prog;
231 }
233 unsigned int create_program_link(unsigned int sdr0, ...)
234 {
235 unsigned int prog, sdr;
236 va_list ap;
238 if(!(prog = create_program())) {
239 return 0;
240 }
242 attach_shader(prog, sdr0);
243 if(glGetError()) {
244 return 0;
245 }
247 va_start(ap, sdr0);
248 while((sdr = va_arg(ap, unsigned int))) {
249 attach_shader(prog, sdr);
250 if(glGetError()) {
251 return 0;
252 }
253 }
254 va_end(ap);
256 if(link_program(prog) == -1) {
257 free_program(prog);
258 return 0;
259 }
260 return prog;
261 }
263 unsigned int create_program_load(const char *vfile, const char *pfile)
264 {
265 unsigned int vs = 0, ps = 0;
267 if(vfile && *vfile && !(vs = get_vertex_shader(vfile))) {
268 return 0;
269 }
270 if(pfile && *pfile && !(ps = get_pixel_shader(pfile))) {
271 return 0;
272 }
273 return create_program_link(vs, ps, 0);
274 }
276 void free_program(unsigned int sdr)
277 {
278 glDeleteProgram(sdr);
279 }
281 void attach_shader(unsigned int prog, unsigned int sdr)
282 {
283 if(prog && sdr) {
284 glAttachShader(prog, sdr);
285 assert(glGetError() == GL_NO_ERROR);
286 }
287 }
289 int link_program(unsigned int prog)
290 {
291 int linked, info_len, retval = 0;
292 char *info_str = 0;
294 glLinkProgram(prog);
295 assert(glGetError() == GL_NO_ERROR);
296 glGetProgramiv(prog, GL_LINK_STATUS, &linked);
297 assert(glGetError() == GL_NO_ERROR);
298 glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &info_len);
299 assert(glGetError() == GL_NO_ERROR);
301 if(info_len) {
302 if((info_str = malloc(info_len + 1))) {
303 glGetProgramInfoLog(prog, info_len, 0, info_str);
304 assert(glGetError() == GL_NO_ERROR);
305 info_str[info_len] = 0;
306 }
307 }
309 if(linked) {
310 fprintf(stderr, info_str ? "linking done: %s\n" : "linking done\n", info_str);
311 } else {
312 fprintf(stderr, info_str ? "linking failed: %s\n" : "linking failed\n", info_str);
313 retval = -1;
314 }
316 free(info_str);
317 return retval;
318 }
320 int bind_program(unsigned int prog)
321 {
322 GLenum err;
324 glUseProgram(prog);
325 if(prog && (err = glGetError()) != GL_NO_ERROR) {
326 /* maybe the program is not linked, try linking first */
327 if(err == GL_INVALID_OPERATION) {
328 if(link_program(prog) == -1) {
329 return -1;
330 }
331 glUseProgram(prog);
332 return glGetError() == GL_NO_ERROR ? 0 : -1;
333 }
334 return -1;
335 }
336 return 0;
337 }
339 /* ugly but I'm not going to write the same bloody code over and over */
340 #define BEGIN_UNIFORM_CODE \
341 int loc, curr_prog; \
342 glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); \
343 if((unsigned int)curr_prog != prog && bind_program(prog) == -1) { \
344 return -1; \
345 } \
346 if((loc = glGetUniformLocation(prog, name)) != -1)
348 #define END_UNIFORM_CODE \
349 if((unsigned int)curr_prog != prog) { \
350 bind_program(curr_prog); \
351 } \
352 return loc == -1 ? -1 : 0
354 int set_uniform_int(unsigned int prog, const char *name, int val)
355 {
356 BEGIN_UNIFORM_CODE {
357 glUniform1i(loc, val);
358 }
359 END_UNIFORM_CODE;
360 }
362 int set_uniform_float(unsigned int prog, const char *name, float val)
363 {
364 BEGIN_UNIFORM_CODE {
365 glUniform1f(loc, val);
366 }
367 END_UNIFORM_CODE;
368 }
370 int set_uniform_float2(unsigned int prog, const char *name, float x, float y)
371 {
372 BEGIN_UNIFORM_CODE {
373 glUniform2f(loc, x, y);
374 }
375 END_UNIFORM_CODE;
376 }
378 int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z)
379 {
380 BEGIN_UNIFORM_CODE {
381 glUniform3f(loc, x, y, z);
382 }
383 END_UNIFORM_CODE;
384 }
386 int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w)
387 {
388 BEGIN_UNIFORM_CODE {
389 glUniform4f(loc, x, y, z, w);
390 }
391 END_UNIFORM_CODE;
392 }
394 int set_uniform_matrix4(unsigned int prog, const char *name, float *mat)
395 {
396 BEGIN_UNIFORM_CODE {
397 glUniformMatrix4fv(loc, 1, GL_FALSE, mat);
398 }
399 END_UNIFORM_CODE;
400 }
402 int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat)
403 {
404 BEGIN_UNIFORM_CODE {
405 glUniformMatrix4fv(loc, 1, GL_TRUE, mat);
406 }
407 END_UNIFORM_CODE;
408 }
410 int get_attrib_loc(unsigned int prog, const char *name)
411 {
412 int loc, curr_prog;
414 glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog);
415 if((unsigned int)curr_prog != prog && bind_program(prog) == -1) {
416 return -1;
417 }
419 loc = glGetAttribLocation(prog, (char*)name);
421 if((unsigned int)curr_prog != prog) {
422 bind_program(curr_prog);
423 }
424 return loc;
425 }
427 void set_attrib_float3(int attr_loc, float x, float y, float z)
428 {
429 glVertexAttrib3f(attr_loc, x, y, z);
430 }
432 static const char *sdrtypestr(unsigned int sdrtype)
433 {
434 switch(sdrtype) {
435 case GL_VERTEX_SHADER:
436 return "vertex";
437 case GL_FRAGMENT_SHADER:
438 return "pixel";
439 #ifdef GL_TESS_CONTROL_SHADER
440 case GL_TESS_CONTROL_SHADER:
441 return "tessellation control";
442 #endif
443 #ifdef GL_TESS_EVALUATION_SHADER
444 case GL_TESS_EVALUATION_SHADER:
445 return "tessellation evaluation";
446 #endif
447 #ifdef GL_GEOMETRY_SHADER
448 case GL_GEOMETRY_SHADER:
449 return "geometry";
450 #endif
452 default:
453 break;
454 }
455 return "<unknown>";
456 }