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