3dphotoshoot
view src/sdr.c @ 27:3d082c566b53
fixed all the bugs, pc version works
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 18 Jun 2015 04:32:25 +0300 |
parents | 4ca4e3c5a754 |
children |
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 "opengl.h"
8 #include "assman.h"
10 #if defined(unix) || defined(__unix__)
11 #include <unistd.h>
12 #include <sys/stat.h>
13 #endif /* unix */
15 #include "sdr.h"
17 static const char *sdrtypestr(unsigned int sdrtype);
19 unsigned int create_vertex_shader(const char *src)
20 {
21 return create_shader(src, GL_VERTEX_SHADER);
22 }
24 unsigned int create_pixel_shader(const char *src)
25 {
26 return create_shader(src, GL_FRAGMENT_SHADER);
27 }
29 unsigned int create_tessctl_shader(const char *src)
30 {
31 #ifdef GL_TESS_CONTROL_SHADER
32 return create_shader(src, GL_TESS_CONTROL_SHADER);
33 #else
34 return 0;
35 #endif
36 }
38 unsigned int create_tesseval_shader(const char *src)
39 {
40 #ifdef GL_TESS_EVALUATION_SHADER
41 return create_shader(src, GL_TESS_EVALUATION_SHADER);
42 #else
43 return 0;
44 #endif
45 }
47 unsigned int create_geometry_shader(const char *src)
48 {
49 #ifdef GL_GEOMETRY_SHADER
50 return create_shader(src, GL_GEOMETRY_SHADER);
51 #else
52 return 0;
53 #endif
54 }
56 unsigned int create_shader(const char *src, unsigned int sdr_type)
57 {
58 unsigned int sdr;
59 int success, info_len;
60 char *info_str = 0;
61 GLenum err;
63 sdr = glCreateShader(sdr_type);
64 assert(glGetError() == GL_NO_ERROR);
65 glShaderSource(sdr, 1, &src, 0);
66 err = glGetError();
67 assert(err == GL_NO_ERROR);
68 glCompileShader(sdr);
69 assert(glGetError() == GL_NO_ERROR);
71 glGetShaderiv(sdr, GL_COMPILE_STATUS, &success);
72 assert(glGetError() == GL_NO_ERROR);
73 glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &info_len);
74 assert(glGetError() == GL_NO_ERROR);
76 if(info_len) {
77 if((info_str = malloc(info_len + 1))) {
78 glGetShaderInfoLog(sdr, info_len, 0, info_str);
79 assert(glGetError() == GL_NO_ERROR);
80 info_str[info_len] = 0;
81 }
82 }
84 if(success) {
85 fprintf(stderr, info_str ? "done: %s\n" : "done\n", info_str);
86 } else {
87 fprintf(stderr, info_str ? "failed: %s\n" : "failed\n", info_str);
88 glDeleteShader(sdr);
89 sdr = 0;
90 }
92 free(info_str);
93 return sdr;
94 }
96 void free_shader(unsigned int sdr)
97 {
98 glDeleteShader(sdr);
99 }
101 unsigned int load_vertex_shader(const char *fname)
102 {
103 return load_shader(fname, GL_VERTEX_SHADER);
104 }
106 unsigned int load_pixel_shader(const char *fname)
107 {
108 return load_shader(fname, GL_FRAGMENT_SHADER);
109 }
111 unsigned int load_tessctl_shader(const char *fname)
112 {
113 #ifdef GL_TESS_CONTROL_SHADER
114 return load_shader(fname, GL_TESS_CONTROL_SHADER);
115 #else
116 return 0;
117 #endif
118 }
120 unsigned int load_tesseval_shader(const char *fname)
121 {
122 #ifdef GL_TESS_EVALUATION_SHADER
123 return load_shader(fname, GL_TESS_EVALUATION_SHADER);
124 #else
125 return 0;
126 #endif
127 }
129 unsigned int load_geometry_shader(const char *fname)
130 {
131 #ifdef GL_GEOMETRY_SHADER
132 return load_shader(fname, GL_GEOMETRY_SHADER);
133 #else
134 return 0;
135 #endif
136 }
138 unsigned int load_shader(const char *fname, unsigned int sdr_type)
139 {
140 unsigned int sdr;
141 size_t filesize;
142 ass_file *fp;
143 char *src;
145 if(!(fp = ass_fopen(fname, "rb"))) {
146 fprintf(stderr, "failed to open shader %s: %s\n", fname, strerror(errno));
147 return 0;
148 }
150 filesize = ass_fseek(fp, 0, SEEK_END);
151 /*filesize = ass_ftell(fp);*/
152 ass_fseek(fp, 0, SEEK_SET);
154 if(!(src = malloc(filesize + 1))) {
155 ass_fclose(fp);
156 return 0;
157 }
158 ass_fread(src, 1, filesize, fp);
159 src[filesize] = 0;
160 ass_fclose(fp);
162 fprintf(stderr, "compiling %s shader: %s... ", sdrtypestr(sdr_type), fname);
163 sdr = create_shader(src, sdr_type);
165 free(src);
166 return sdr;
167 }
170 /* ---- gpu programs ---- */
172 unsigned int create_program(void)
173 {
174 unsigned int prog = glCreateProgram();
175 assert(glGetError() == GL_NO_ERROR);
176 return prog;
177 }
179 unsigned int create_program_link(unsigned int sdr0, ...)
180 {
181 unsigned int prog, sdr;
182 va_list ap;
184 if(!(prog = create_program())) {
185 return 0;
186 }
188 attach_shader(prog, sdr0);
189 if(glGetError()) {
190 return 0;
191 }
193 va_start(ap, sdr0);
194 while((sdr = va_arg(ap, unsigned int))) {
195 attach_shader(prog, sdr);
196 if(glGetError()) {
197 return 0;
198 }
199 }
200 va_end(ap);
202 if(link_program(prog) == -1) {
203 free_program(prog);
204 return 0;
205 }
206 return prog;
207 }
209 unsigned int create_program_load(const char *vfile, const char *pfile)
210 {
211 unsigned int vs = 0, ps = 0;
213 if(vfile && *vfile && !(vs = load_vertex_shader(vfile))) {
214 return 0;
215 }
216 if(pfile && *pfile && !(ps = load_pixel_shader(pfile))) {
217 return 0;
218 }
219 return create_program_link(vs, ps, 0);
220 }
222 void free_program(unsigned int sdr)
223 {
224 glDeleteProgram(sdr);
225 }
227 void attach_shader(unsigned int prog, unsigned int sdr)
228 {
229 int err;
231 if(prog && sdr) {
232 assert(glGetError() == GL_NO_ERROR);
233 glAttachShader(prog, sdr);
234 if((err = glGetError()) != GL_NO_ERROR) {
235 fprintf(stderr, "failed to attach shader %u to program %u (err: 0x%x)\n", sdr, prog, err);
236 abort();
237 }
238 }
239 }
241 int link_program(unsigned int prog)
242 {
243 int linked, info_len, retval = 0;
244 char *info_str = 0;
246 glLinkProgram(prog);
247 assert(glGetError() == GL_NO_ERROR);
248 glGetProgramiv(prog, GL_LINK_STATUS, &linked);
249 assert(glGetError() == GL_NO_ERROR);
250 glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &info_len);
251 assert(glGetError() == GL_NO_ERROR);
253 if(info_len) {
254 if((info_str = malloc(info_len + 1))) {
255 glGetProgramInfoLog(prog, info_len, 0, info_str);
256 assert(glGetError() == GL_NO_ERROR);
257 info_str[info_len] = 0;
258 }
259 }
261 if(linked) {
262 fprintf(stderr, info_str ? "linking done: %s\n" : "linking done\n", info_str);
263 } else {
264 fprintf(stderr, info_str ? "linking failed: %s\n" : "linking failed\n", info_str);
265 retval = -1;
266 }
268 free(info_str);
269 return retval;
270 }
272 int bind_program(unsigned int prog)
273 {
274 GLenum err;
276 glUseProgram(prog);
277 if(prog && (err = glGetError()) != GL_NO_ERROR) {
278 /* maybe the program is not linked, try linking first */
279 if(err == GL_INVALID_OPERATION) {
280 if(link_program(prog) == -1) {
281 return -1;
282 }
283 glUseProgram(prog);
284 return glGetError() == GL_NO_ERROR ? 0 : -1;
285 }
286 return -1;
287 }
288 return 0;
289 }
291 /* ugly but I'm not going to write the same bloody code over and over */
292 #define BEGIN_UNIFORM_CODE \
293 int loc, curr_prog; \
294 glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); \
295 if((unsigned int)curr_prog != prog && bind_program(prog) == -1) { \
296 return -1; \
297 } \
298 if((loc = glGetUniformLocation(prog, name)) != -1)
300 #define END_UNIFORM_CODE \
301 if((unsigned int)curr_prog != prog) { \
302 bind_program(curr_prog); \
303 } \
304 return loc == -1 ? -1 : 0
306 int set_uniform_int(unsigned int prog, const char *name, int val)
307 {
308 BEGIN_UNIFORM_CODE {
309 glUniform1i(loc, val);
310 }
311 END_UNIFORM_CODE;
312 }
314 int set_uniform_float(unsigned int prog, const char *name, float val)
315 {
316 BEGIN_UNIFORM_CODE {
317 glUniform1f(loc, val);
318 }
319 END_UNIFORM_CODE;
320 }
322 int set_uniform_float2(unsigned int prog, const char *name, float x, float y)
323 {
324 BEGIN_UNIFORM_CODE {
325 glUniform2f(loc, x, y);
326 }
327 END_UNIFORM_CODE;
328 }
330 int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z)
331 {
332 BEGIN_UNIFORM_CODE {
333 glUniform3f(loc, x, y, z);
334 }
335 END_UNIFORM_CODE;
336 }
338 int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w)
339 {
340 BEGIN_UNIFORM_CODE {
341 glUniform4f(loc, x, y, z, w);
342 }
343 END_UNIFORM_CODE;
344 }
346 int set_uniform_matrix4(unsigned int prog, const char *name, float *mat)
347 {
348 BEGIN_UNIFORM_CODE {
349 glUniformMatrix4fv(loc, 1, GL_FALSE, mat);
350 }
351 END_UNIFORM_CODE;
352 }
354 int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat)
355 {
356 BEGIN_UNIFORM_CODE {
357 glUniformMatrix4fv(loc, 1, GL_TRUE, mat);
358 }
359 END_UNIFORM_CODE;
360 }
362 int get_attrib_loc(unsigned int prog, const char *name)
363 {
364 int loc, curr_prog;
366 glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog);
367 if((unsigned int)curr_prog != prog && bind_program(prog) == -1) {
368 return -1;
369 }
371 loc = glGetAttribLocation(prog, (char*)name);
373 if((unsigned int)curr_prog != prog) {
374 bind_program(curr_prog);
375 }
376 return loc;
377 }
379 void set_attrib_float3(int attr_loc, float x, float y, float z)
380 {
381 glVertexAttrib3f(attr_loc, x, y, z);
382 }
384 static const char *sdrtypestr(unsigned int sdrtype)
385 {
386 switch(sdrtype) {
387 case GL_VERTEX_SHADER:
388 return "vertex";
389 case GL_FRAGMENT_SHADER:
390 return "pixel";
391 #ifdef GL_TESS_CONTROL_SHADER
392 case GL_TESS_CONTROL_SHADER:
393 return "tessellation control";
394 #endif
395 #ifdef GL_TESS_EVALUATION_SHADER
396 case GL_TESS_EVALUATION_SHADER:
397 return "tessellation evaluation";
398 #endif
399 #ifdef GL_GEOMETRY_SHADER
400 case GL_GEOMETRY_SHADER:
401 return "geometry";
402 #endif
404 default:
405 break;
406 }
407 return "<unknown>";
408 }