qvolray
diff src/sdr.c @ 0:b050ce167ff1
foo
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 31 Mar 2012 02:08:42 +0300 |
parents | |
children | 17d9dc2edc91 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/sdr.c Sat Mar 31 02:08:42 2012 +0300 1.3 @@ -0,0 +1,333 @@ 1.4 +#ifndef NO_SHADERS 1.5 + 1.6 +#include <stdio.h> 1.7 +#include <stdlib.h> 1.8 +#include <string.h> 1.9 +#include <errno.h> 1.10 +#include <assert.h> 1.11 +#include <GL/glew.h> 1.12 + 1.13 +#if defined(unix) || defined(__unix__) 1.14 +#include <unistd.h> 1.15 +#include <sys/stat.h> 1.16 +#endif /* unix */ 1.17 + 1.18 +#include "sdr.h" 1.19 + 1.20 +unsigned int create_vertex_shader(const char *src) 1.21 +{ 1.22 + return create_shader(src, GL_VERTEX_SHADER); 1.23 +} 1.24 + 1.25 +unsigned int create_pixel_shader(const char *src) 1.26 +{ 1.27 + return create_shader(src, GL_FRAGMENT_SHADER); 1.28 +} 1.29 + 1.30 +unsigned int create_shader(const char *src, unsigned int sdr_type) 1.31 +{ 1.32 + unsigned int sdr; 1.33 + int success, info_len; 1.34 + char *info_str = 0; 1.35 + GLenum err; 1.36 + 1.37 + sdr = glCreateShader(sdr_type); 1.38 + assert(glGetError() == GL_NO_ERROR); 1.39 + glShaderSource(sdr, 1, &src, 0); 1.40 + err = glGetError(); 1.41 + assert(err == GL_NO_ERROR); 1.42 + glCompileShader(sdr); 1.43 + assert(glGetError() == GL_NO_ERROR); 1.44 + 1.45 + glGetShaderiv(sdr, GL_COMPILE_STATUS, &success); 1.46 + assert(glGetError() == GL_NO_ERROR); 1.47 + glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &info_len); 1.48 + assert(glGetError() == GL_NO_ERROR); 1.49 + 1.50 + if(info_len) { 1.51 + if((info_str = malloc(info_len + 1))) { 1.52 + glGetShaderInfoLog(sdr, info_len, 0, info_str); 1.53 + assert(glGetError() == GL_NO_ERROR); 1.54 + } 1.55 + } 1.56 + 1.57 + if(success) { 1.58 + fprintf(stderr, info_str ? "done: %s\n" : "done\n", info_str); 1.59 + } else { 1.60 + fprintf(stderr, info_str ? "failed: %s\n" : "failed\n", info_str); 1.61 + glDeleteShader(sdr); 1.62 + sdr = 0; 1.63 + } 1.64 + 1.65 + free(info_str); 1.66 + return sdr; 1.67 +} 1.68 + 1.69 +void free_shader(unsigned int sdr) 1.70 +{ 1.71 + glDeleteShader(sdr); 1.72 +} 1.73 + 1.74 +unsigned int load_vertex_shader(const char *fname) 1.75 +{ 1.76 + return load_shader(fname, GL_VERTEX_SHADER); 1.77 +} 1.78 + 1.79 +unsigned int load_pixel_shader(const char *fname) 1.80 +{ 1.81 + return load_shader(fname, GL_FRAGMENT_SHADER); 1.82 +} 1.83 + 1.84 +unsigned int load_shader(const char *fname, unsigned int sdr_type) 1.85 +{ 1.86 +#if defined(unix) || defined(__unix__) 1.87 + struct stat st; 1.88 +#endif 1.89 + unsigned int sdr; 1.90 + size_t filesize; 1.91 + FILE *fp; 1.92 + char *src; 1.93 + 1.94 + if(!(fp = fopen(fname, "r"))) { 1.95 + fprintf(stderr, "failed to open shader %s: %s\n", fname, strerror(errno)); 1.96 + return 0; 1.97 + } 1.98 + 1.99 +#if defined(unix) || defined(__unix__) 1.100 + fstat(fileno(fp), &st); 1.101 + filesize = st.st_size; 1.102 +#else 1.103 + fseek(fp, 0, SEEK_END); 1.104 + filesize = ftell(fp); 1.105 + fseek(fp, 0, SEEK_SET); 1.106 +#endif /* unix */ 1.107 + 1.108 + if(!(src = malloc(filesize + 1))) { 1.109 + fclose(fp); 1.110 + return 0; 1.111 + } 1.112 + fread(src, 1, filesize, fp); 1.113 + src[filesize] = 0; 1.114 + fclose(fp); 1.115 + 1.116 + fprintf(stderr, "compiling %s shader: %s... ", (sdr_type == GL_VERTEX_SHADER ? "vertex" : "pixel"), fname); 1.117 + sdr = create_shader(src, sdr_type); 1.118 + 1.119 + free(src); 1.120 + return sdr; 1.121 +} 1.122 + 1.123 + 1.124 +unsigned int get_vertex_shader(const char *fname) 1.125 +{ 1.126 + return get_shader(fname, GL_VERTEX_SHADER); 1.127 +} 1.128 + 1.129 +unsigned int get_pixel_shader(const char *fname) 1.130 +{ 1.131 + return get_shader(fname, GL_FRAGMENT_SHADER); 1.132 +} 1.133 + 1.134 +unsigned int get_shader(const char *fname, unsigned int sdr_type) 1.135 +{ 1.136 + unsigned int sdr; 1.137 + 1.138 + if(!(sdr = load_shader(fname, sdr_type))) { 1.139 + return 0; 1.140 + } 1.141 + return sdr; 1.142 +} 1.143 + 1.144 + 1.145 +/* ---- gpu programs ---- */ 1.146 + 1.147 +unsigned int create_program(void) 1.148 +{ 1.149 + unsigned int prog = glCreateProgram(); 1.150 + assert(glGetError() == GL_NO_ERROR); 1.151 + return prog; 1.152 +} 1.153 + 1.154 +unsigned int create_program_link(unsigned int vs, unsigned int ps) 1.155 +{ 1.156 + unsigned int prog; 1.157 + 1.158 + if(!(prog = create_program())) { 1.159 + return 0; 1.160 + } 1.161 + 1.162 + if(vs) { 1.163 + attach_shader(prog, vs); 1.164 + assert(glGetError() == GL_NO_ERROR); 1.165 + } 1.166 + if(ps) { 1.167 + attach_shader(prog, ps); 1.168 + assert(glGetError() == GL_NO_ERROR); 1.169 + } 1.170 + 1.171 + if(link_program(prog) == -1) { 1.172 + free_program(prog); 1.173 + return 0; 1.174 + } 1.175 + return prog; 1.176 +} 1.177 + 1.178 +unsigned int create_program_load(const char *vfile, const char *pfile) 1.179 +{ 1.180 + unsigned int vs = 0, ps = 0; 1.181 + 1.182 + if(vfile && !(vs = get_vertex_shader(vfile))) { 1.183 + return 0; 1.184 + } 1.185 + if(pfile && !(ps = get_pixel_shader(pfile))) { 1.186 + return 0; 1.187 + } 1.188 + return create_program_link(vs, ps); 1.189 +} 1.190 + 1.191 +void free_program(unsigned int sdr) 1.192 +{ 1.193 + glDeleteProgram(sdr); 1.194 +} 1.195 + 1.196 +void attach_shader(unsigned int prog, unsigned int sdr) 1.197 +{ 1.198 + glAttachShader(prog, sdr); 1.199 + assert(glGetError() == GL_NO_ERROR); 1.200 +} 1.201 + 1.202 +int link_program(unsigned int prog) 1.203 +{ 1.204 + int linked, info_len, retval = 0; 1.205 + char *info_str = 0; 1.206 + 1.207 + glLinkProgram(prog); 1.208 + assert(glGetError() == GL_NO_ERROR); 1.209 + glGetProgramiv(prog, GL_LINK_STATUS, &linked); 1.210 + assert(glGetError() == GL_NO_ERROR); 1.211 + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &info_len); 1.212 + assert(glGetError() == GL_NO_ERROR); 1.213 + 1.214 + if(info_len) { 1.215 + if((info_str = malloc(info_len + 1))) { 1.216 + glGetProgramInfoLog(prog, info_len, 0, info_str); 1.217 + assert(glGetError() == GL_NO_ERROR); 1.218 + } 1.219 + } 1.220 + 1.221 + if(linked) { 1.222 + fprintf(stderr, info_str ? "linking done: %s\n" : "linking done\n", info_str); 1.223 + } else { 1.224 + fprintf(stderr, info_str ? "linking failed: %s\n" : "linking failed\n", info_str); 1.225 + retval = -1; 1.226 + } 1.227 + 1.228 + free(info_str); 1.229 + return retval; 1.230 +} 1.231 + 1.232 +int bind_program(unsigned int prog) 1.233 +{ 1.234 + GLenum err; 1.235 + 1.236 + glUseProgram(prog); 1.237 + if(prog && (err = glGetError()) != GL_NO_ERROR) { 1.238 + /* maybe the program is not linked, try linking first */ 1.239 + if(err == GL_INVALID_OPERATION) { 1.240 + if(link_program(prog) == -1) { 1.241 + return -1; 1.242 + } 1.243 + glUseProgram(prog); 1.244 + return glGetError() == GL_NO_ERROR ? 0 : -1; 1.245 + } 1.246 + return -1; 1.247 + } 1.248 + return 0; 1.249 +} 1.250 + 1.251 +/* ugly but I'm not going to write the same bloody code over and over */ 1.252 +#define BEGIN_UNIFORM_CODE \ 1.253 + int loc, curr_prog; \ 1.254 + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); \ 1.255 + if(curr_prog != prog && bind_program(prog) == -1) { \ 1.256 + return -1; \ 1.257 + } \ 1.258 + if((loc = glGetUniformLocation(prog, name)) != -1) 1.259 + 1.260 +#define END_UNIFORM_CODE \ 1.261 + if(curr_prog != prog) { \ 1.262 + bind_program(curr_prog); \ 1.263 + } \ 1.264 + return loc == -1 ? -1 : 0 1.265 + 1.266 +int set_uniform_int(unsigned int prog, const char *name, int val) 1.267 +{ 1.268 + BEGIN_UNIFORM_CODE { 1.269 + glUniform1i(loc, val); 1.270 + } 1.271 + END_UNIFORM_CODE; 1.272 +} 1.273 + 1.274 +int set_uniform_float(unsigned int prog, const char *name, float val) 1.275 +{ 1.276 + BEGIN_UNIFORM_CODE { 1.277 + glUniform1f(loc, val); 1.278 + } 1.279 + END_UNIFORM_CODE; 1.280 +} 1.281 + 1.282 +int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z) 1.283 +{ 1.284 + BEGIN_UNIFORM_CODE { 1.285 + glUniform3f(loc, x, y, z); 1.286 + } 1.287 + END_UNIFORM_CODE; 1.288 +} 1.289 + 1.290 +int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w) 1.291 +{ 1.292 + BEGIN_UNIFORM_CODE { 1.293 + glUniform4f(loc, x, y, z, w); 1.294 + } 1.295 + END_UNIFORM_CODE; 1.296 +} 1.297 + 1.298 +int set_uniform_matrix4(unsigned int prog, const char *name, float *mat) 1.299 +{ 1.300 + BEGIN_UNIFORM_CODE { 1.301 + glUniformMatrix4fv(loc, 1, GL_FALSE, mat); 1.302 + } 1.303 + END_UNIFORM_CODE; 1.304 +} 1.305 + 1.306 +int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat) 1.307 +{ 1.308 + BEGIN_UNIFORM_CODE { 1.309 + glUniformMatrix4fv(loc, 1, GL_TRUE, mat); 1.310 + } 1.311 + END_UNIFORM_CODE; 1.312 +} 1.313 + 1.314 +int get_attrib_loc(unsigned int prog, const char *name) 1.315 +{ 1.316 + int loc, curr_prog; 1.317 + 1.318 + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); 1.319 + if(curr_prog != prog && bind_program(prog) == -1) { 1.320 + return -1; 1.321 + } 1.322 + 1.323 + loc = glGetAttribLocation(prog, (char*)name); 1.324 + 1.325 + if(curr_prog != prog) { 1.326 + bind_program(curr_prog); 1.327 + } 1.328 + return loc; 1.329 +} 1.330 + 1.331 +void set_attrib_float3(int attr_loc, float x, float y, float z) 1.332 +{ 1.333 + glVertexAttrib3f(attr_loc, x, y, z); 1.334 +} 1.335 + 1.336 +#endif /* !NO_SHADERS */