3dphotoshoot
diff src/sdr.c @ 10:c71c477521ca
converting to GLES2 and C++
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 31 May 2015 00:40:26 +0300 |
parents | |
children | aef7f51f6397 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/sdr.c Sun May 31 00:40:26 2015 +0300 1.3 @@ -0,0 +1,412 @@ 1.4 +#include <stdio.h> 1.5 +#include <stdlib.h> 1.6 +#include <string.h> 1.7 +#include <errno.h> 1.8 +#include <stdarg.h> 1.9 +#include <assert.h> 1.10 +#include "opengl.h" 1.11 + 1.12 +#if defined(unix) || defined(__unix__) 1.13 +#include <unistd.h> 1.14 +#include <sys/stat.h> 1.15 +#endif /* unix */ 1.16 + 1.17 +#include "sdr.h" 1.18 + 1.19 +static const char *sdrtypestr(unsigned int sdrtype); 1.20 + 1.21 +unsigned int create_vertex_shader(const char *src) 1.22 +{ 1.23 + return create_shader(src, GL_VERTEX_SHADER); 1.24 +} 1.25 + 1.26 +unsigned int create_pixel_shader(const char *src) 1.27 +{ 1.28 + return create_shader(src, GL_FRAGMENT_SHADER); 1.29 +} 1.30 + 1.31 +unsigned int create_tessctl_shader(const char *src) 1.32 +{ 1.33 +#ifdef GL_TESS_CONTROL_SHADER 1.34 + return create_shader(src, GL_TESS_CONTROL_SHADER); 1.35 +#else 1.36 + return 0; 1.37 +#endif 1.38 +} 1.39 + 1.40 +unsigned int create_tesseval_shader(const char *src) 1.41 +{ 1.42 +#ifdef GL_TESS_EVALUATION_SHADER 1.43 + return create_shader(src, GL_TESS_EVALUATION_SHADER); 1.44 +#else 1.45 + return 0; 1.46 +#endif 1.47 +} 1.48 + 1.49 +unsigned int create_geometry_shader(const char *src) 1.50 +{ 1.51 +#ifdef GL_GEOMETRY_SHADER 1.52 + return create_shader(src, GL_GEOMETRY_SHADER); 1.53 +#else 1.54 + return 0; 1.55 +#endif 1.56 +} 1.57 + 1.58 +unsigned int create_shader(const char *src, unsigned int sdr_type) 1.59 +{ 1.60 + unsigned int sdr; 1.61 + int success, info_len; 1.62 + char *info_str = 0; 1.63 + GLenum err; 1.64 + 1.65 + sdr = glCreateShader(sdr_type); 1.66 + assert(glGetError() == GL_NO_ERROR); 1.67 + glShaderSource(sdr, 1, &src, 0); 1.68 + err = glGetError(); 1.69 + assert(err == GL_NO_ERROR); 1.70 + glCompileShader(sdr); 1.71 + assert(glGetError() == GL_NO_ERROR); 1.72 + 1.73 + glGetShaderiv(sdr, GL_COMPILE_STATUS, &success); 1.74 + assert(glGetError() == GL_NO_ERROR); 1.75 + glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &info_len); 1.76 + assert(glGetError() == GL_NO_ERROR); 1.77 + 1.78 + if(info_len) { 1.79 + if((info_str = malloc(info_len + 1))) { 1.80 + glGetShaderInfoLog(sdr, info_len, 0, info_str); 1.81 + assert(glGetError() == GL_NO_ERROR); 1.82 + info_str[info_len] = 0; 1.83 + } 1.84 + } 1.85 + 1.86 + if(success) { 1.87 + fprintf(stderr, info_str ? "done: %s\n" : "done\n", info_str); 1.88 + } else { 1.89 + fprintf(stderr, info_str ? "failed: %s\n" : "failed\n", info_str); 1.90 + glDeleteShader(sdr); 1.91 + sdr = 0; 1.92 + } 1.93 + 1.94 + free(info_str); 1.95 + return sdr; 1.96 +} 1.97 + 1.98 +void free_shader(unsigned int sdr) 1.99 +{ 1.100 + glDeleteShader(sdr); 1.101 +} 1.102 + 1.103 +unsigned int load_vertex_shader(const char *fname) 1.104 +{ 1.105 + return load_shader(fname, GL_VERTEX_SHADER); 1.106 +} 1.107 + 1.108 +unsigned int load_pixel_shader(const char *fname) 1.109 +{ 1.110 + return load_shader(fname, GL_FRAGMENT_SHADER); 1.111 +} 1.112 + 1.113 +unsigned int load_tessctl_shader(const char *fname) 1.114 +{ 1.115 +#ifdef GL_TESS_CONTROL_SHADER 1.116 + return load_shader(fname, GL_TESS_CONTROL_SHADER); 1.117 +#else 1.118 + return 0; 1.119 +#endif 1.120 +} 1.121 + 1.122 +unsigned int load_tesseval_shader(const char *fname) 1.123 +{ 1.124 +#ifdef GL_TESS_EVALUATION_SHADER 1.125 + return load_shader(fname, GL_TESS_EVALUATION_SHADER); 1.126 +#else 1.127 + return 0; 1.128 +#endif 1.129 +} 1.130 + 1.131 +unsigned int load_geometry_shader(const char *fname) 1.132 +{ 1.133 +#ifdef GL_GEOMETRY_SHADER 1.134 + return load_shader(fname, GL_GEOMETRY_SHADER); 1.135 +#else 1.136 + return 0; 1.137 +#endif 1.138 +} 1.139 + 1.140 +unsigned int load_shader(const char *fname, unsigned int sdr_type) 1.141 +{ 1.142 +#if defined(unix) || defined(__unix__) 1.143 + struct stat st; 1.144 +#endif 1.145 + unsigned int sdr; 1.146 + size_t filesize; 1.147 + FILE *fp; 1.148 + char *src; 1.149 + 1.150 + if(!(fp = fopen(fname, "rb"))) { 1.151 + fprintf(stderr, "failed to open shader %s: %s\n", fname, strerror(errno)); 1.152 + return 0; 1.153 + } 1.154 + 1.155 +#if defined(unix) || defined(__unix__) 1.156 + fstat(fileno(fp), &st); 1.157 + filesize = st.st_size; 1.158 +#else 1.159 + fseek(fp, 0, SEEK_END); 1.160 + filesize = ftell(fp); 1.161 + fseek(fp, 0, SEEK_SET); 1.162 +#endif /* unix */ 1.163 + 1.164 + if(!(src = malloc(filesize + 1))) { 1.165 + fclose(fp); 1.166 + return 0; 1.167 + } 1.168 + fread(src, 1, filesize, fp); 1.169 + src[filesize] = 0; 1.170 + fclose(fp); 1.171 + 1.172 + fprintf(stderr, "compiling %s shader: %s... ", sdrtypestr(sdr_type), fname); 1.173 + sdr = create_shader(src, sdr_type); 1.174 + 1.175 + free(src); 1.176 + return sdr; 1.177 +} 1.178 + 1.179 + 1.180 +/* ---- gpu programs ---- */ 1.181 + 1.182 +unsigned int create_program(void) 1.183 +{ 1.184 + unsigned int prog = glCreateProgram(); 1.185 + assert(glGetError() == GL_NO_ERROR); 1.186 + return prog; 1.187 +} 1.188 + 1.189 +unsigned int create_program_link(unsigned int sdr0, ...) 1.190 +{ 1.191 + unsigned int prog, sdr; 1.192 + va_list ap; 1.193 + 1.194 + if(!(prog = create_program())) { 1.195 + return 0; 1.196 + } 1.197 + 1.198 + attach_shader(prog, sdr0); 1.199 + if(glGetError()) { 1.200 + return 0; 1.201 + } 1.202 + 1.203 + va_start(ap, sdr0); 1.204 + while((sdr = va_arg(ap, unsigned int))) { 1.205 + attach_shader(prog, sdr); 1.206 + if(glGetError()) { 1.207 + return 0; 1.208 + } 1.209 + } 1.210 + va_end(ap); 1.211 + 1.212 + if(link_program(prog) == -1) { 1.213 + free_program(prog); 1.214 + return 0; 1.215 + } 1.216 + return prog; 1.217 +} 1.218 + 1.219 +unsigned int create_program_load(const char *vfile, const char *pfile) 1.220 +{ 1.221 + unsigned int vs = 0, ps = 0; 1.222 + 1.223 + if(vfile && *vfile && !(vs = load_vertex_shader(vfile))) { 1.224 + return 0; 1.225 + } 1.226 + if(pfile && *pfile && !(ps = load_pixel_shader(pfile))) { 1.227 + return 0; 1.228 + } 1.229 + return create_program_link(vs, ps, 0); 1.230 +} 1.231 + 1.232 +void free_program(unsigned int sdr) 1.233 +{ 1.234 + glDeleteProgram(sdr); 1.235 +} 1.236 + 1.237 +void attach_shader(unsigned int prog, unsigned int sdr) 1.238 +{ 1.239 + if(prog && sdr) { 1.240 + glAttachShader(prog, sdr); 1.241 + if(glGetError() != GL_NO_ERROR) { 1.242 + fprintf(stderr, "failed to attach shader %u to program %u\n", sdr, prog); 1.243 + abort(); 1.244 + } 1.245 + } 1.246 +} 1.247 + 1.248 +int link_program(unsigned int prog) 1.249 +{ 1.250 + int linked, info_len, retval = 0; 1.251 + char *info_str = 0; 1.252 + 1.253 + glLinkProgram(prog); 1.254 + assert(glGetError() == GL_NO_ERROR); 1.255 + glGetProgramiv(prog, GL_LINK_STATUS, &linked); 1.256 + assert(glGetError() == GL_NO_ERROR); 1.257 + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &info_len); 1.258 + assert(glGetError() == GL_NO_ERROR); 1.259 + 1.260 + if(info_len) { 1.261 + if((info_str = malloc(info_len + 1))) { 1.262 + glGetProgramInfoLog(prog, info_len, 0, info_str); 1.263 + assert(glGetError() == GL_NO_ERROR); 1.264 + info_str[info_len] = 0; 1.265 + } 1.266 + } 1.267 + 1.268 + if(linked) { 1.269 + fprintf(stderr, info_str ? "linking done: %s\n" : "linking done\n", info_str); 1.270 + } else { 1.271 + fprintf(stderr, info_str ? "linking failed: %s\n" : "linking failed\n", info_str); 1.272 + retval = -1; 1.273 + } 1.274 + 1.275 + free(info_str); 1.276 + return retval; 1.277 +} 1.278 + 1.279 +int bind_program(unsigned int prog) 1.280 +{ 1.281 + GLenum err; 1.282 + 1.283 + glUseProgram(prog); 1.284 + if(prog && (err = glGetError()) != GL_NO_ERROR) { 1.285 + /* maybe the program is not linked, try linking first */ 1.286 + if(err == GL_INVALID_OPERATION) { 1.287 + if(link_program(prog) == -1) { 1.288 + return -1; 1.289 + } 1.290 + glUseProgram(prog); 1.291 + return glGetError() == GL_NO_ERROR ? 0 : -1; 1.292 + } 1.293 + return -1; 1.294 + } 1.295 + return 0; 1.296 +} 1.297 + 1.298 +/* ugly but I'm not going to write the same bloody code over and over */ 1.299 +#define BEGIN_UNIFORM_CODE \ 1.300 + int loc, curr_prog; \ 1.301 + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); \ 1.302 + if((unsigned int)curr_prog != prog && bind_program(prog) == -1) { \ 1.303 + return -1; \ 1.304 + } \ 1.305 + if((loc = glGetUniformLocation(prog, name)) != -1) 1.306 + 1.307 +#define END_UNIFORM_CODE \ 1.308 + if((unsigned int)curr_prog != prog) { \ 1.309 + bind_program(curr_prog); \ 1.310 + } \ 1.311 + return loc == -1 ? -1 : 0 1.312 + 1.313 +int set_uniform_int(unsigned int prog, const char *name, int val) 1.314 +{ 1.315 + BEGIN_UNIFORM_CODE { 1.316 + glUniform1i(loc, val); 1.317 + } 1.318 + END_UNIFORM_CODE; 1.319 +} 1.320 + 1.321 +int set_uniform_float(unsigned int prog, const char *name, float val) 1.322 +{ 1.323 + BEGIN_UNIFORM_CODE { 1.324 + glUniform1f(loc, val); 1.325 + } 1.326 + END_UNIFORM_CODE; 1.327 +} 1.328 + 1.329 +int set_uniform_float2(unsigned int prog, const char *name, float x, float y) 1.330 +{ 1.331 + BEGIN_UNIFORM_CODE { 1.332 + glUniform2f(loc, x, y); 1.333 + } 1.334 + END_UNIFORM_CODE; 1.335 +} 1.336 + 1.337 +int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z) 1.338 +{ 1.339 + BEGIN_UNIFORM_CODE { 1.340 + glUniform3f(loc, x, y, z); 1.341 + } 1.342 + END_UNIFORM_CODE; 1.343 +} 1.344 + 1.345 +int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w) 1.346 +{ 1.347 + BEGIN_UNIFORM_CODE { 1.348 + glUniform4f(loc, x, y, z, w); 1.349 + } 1.350 + END_UNIFORM_CODE; 1.351 +} 1.352 + 1.353 +int set_uniform_matrix4(unsigned int prog, const char *name, float *mat) 1.354 +{ 1.355 + BEGIN_UNIFORM_CODE { 1.356 + glUniformMatrix4fv(loc, 1, GL_FALSE, mat); 1.357 + } 1.358 + END_UNIFORM_CODE; 1.359 +} 1.360 + 1.361 +int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat) 1.362 +{ 1.363 + BEGIN_UNIFORM_CODE { 1.364 + glUniformMatrix4fv(loc, 1, GL_TRUE, mat); 1.365 + } 1.366 + END_UNIFORM_CODE; 1.367 +} 1.368 + 1.369 +int get_attrib_loc(unsigned int prog, const char *name) 1.370 +{ 1.371 + int loc, curr_prog; 1.372 + 1.373 + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); 1.374 + if((unsigned int)curr_prog != prog && bind_program(prog) == -1) { 1.375 + return -1; 1.376 + } 1.377 + 1.378 + loc = glGetAttribLocation(prog, (char*)name); 1.379 + 1.380 + if((unsigned int)curr_prog != prog) { 1.381 + bind_program(curr_prog); 1.382 + } 1.383 + return loc; 1.384 +} 1.385 + 1.386 +void set_attrib_float3(int attr_loc, float x, float y, float z) 1.387 +{ 1.388 + glVertexAttrib3f(attr_loc, x, y, z); 1.389 +} 1.390 + 1.391 +static const char *sdrtypestr(unsigned int sdrtype) 1.392 +{ 1.393 + switch(sdrtype) { 1.394 + case GL_VERTEX_SHADER: 1.395 + return "vertex"; 1.396 + case GL_FRAGMENT_SHADER: 1.397 + return "pixel"; 1.398 +#ifdef GL_TESS_CONTROL_SHADER 1.399 + case GL_TESS_CONTROL_SHADER: 1.400 + return "tessellation control"; 1.401 +#endif 1.402 +#ifdef GL_TESS_EVALUATION_SHADER 1.403 + case GL_TESS_EVALUATION_SHADER: 1.404 + return "tessellation evaluation"; 1.405 +#endif 1.406 +#ifdef GL_GEOMETRY_SHADER 1.407 + case GL_GEOMETRY_SHADER: 1.408 + return "geometry"; 1.409 +#endif 1.410 + 1.411 + default: 1.412 + break; 1.413 + } 1.414 + return "<unknown>"; 1.415 +}