stereoplay

view src/sdr.c @ 4:acf3d25f23cb

added license headings
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 03 Nov 2011 21:57:12 +0200
parents 265a24704ff2
children
line source
1 /*
2 Stereoplay - an OpenGL stereoscopic video player.
3 Copyright (C) 2011 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <assert.h>
24 #include <GL/glew.h>
26 #if defined(unix) || defined(__unix__) || defined(__APPLE__)
27 #include <unistd.h>
28 #include <sys/stat.h>
29 #endif /* unix */
31 #include "sdr.h"
33 unsigned int create_vertex_shader(const char *src)
34 {
35 return create_shader(src, GL_VERTEX_SHADER);
36 }
38 unsigned int create_pixel_shader(const char *src)
39 {
40 return create_shader(src, GL_FRAGMENT_SHADER);
41 }
43 unsigned int create_shader(const char *src, unsigned int sdr_type)
44 {
45 unsigned int sdr;
46 int success, info_len;
47 char *info_str = 0;
48 GLenum err;
50 sdr = glCreateShader(sdr_type);
51 assert(glGetError() == GL_NO_ERROR);
52 glShaderSource(sdr, 1, &src, 0);
53 err = glGetError();
54 assert(err == GL_NO_ERROR);
55 glCompileShader(sdr);
56 assert(glGetError() == GL_NO_ERROR);
58 glGetShaderiv(sdr, GL_COMPILE_STATUS, &success);
59 assert(glGetError() == GL_NO_ERROR);
60 glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &info_len);
61 assert(glGetError() == GL_NO_ERROR);
63 if(info_len) {
64 if((info_str = malloc(info_len + 1))) {
65 glGetShaderInfoLog(sdr, info_len, 0, info_str);
66 assert(glGetError() == GL_NO_ERROR);
67 }
68 }
70 if(success) {
71 fprintf(stderr, info_str ? "done: %s\n" : "done\n", info_str);
72 } else {
73 fprintf(stderr, info_str ? "failed: %s\n" : "failed\n", info_str);
74 glDeleteShader(sdr);
75 sdr = 0;
76 }
78 free(info_str);
79 return sdr;
80 }
82 void free_shader(unsigned int sdr)
83 {
84 glDeleteShader(sdr);
85 }
87 unsigned int load_vertex_shader(const char *fname)
88 {
89 return load_shader(fname, GL_VERTEX_SHADER);
90 }
92 unsigned int load_pixel_shader(const char *fname)
93 {
94 return load_shader(fname, GL_FRAGMENT_SHADER);
95 }
97 unsigned int load_shader(const char *fname, unsigned int sdr_type)
98 {
99 #if defined(unix) || defined(__unix__)
100 struct stat st;
101 #endif
102 unsigned int sdr;
103 size_t filesize;
104 FILE *fp;
105 char *src;
107 if(!(fp = fopen(fname, "r"))) {
108 fprintf(stderr, "failed to open shader %s: %s\n", fname, strerror(errno));
109 return 0;
110 }
112 #if defined(unix) || defined(__unix__) || defined(__APPLE__)
113 fstat(fileno(fp), &st);
114 filesize = st.st_size;
115 #else
116 fseek(fp, 0, SEEK_END);
117 filesize = ftell(fp);
118 fseek(fp, 0, SEEK_SET);
119 #endif /* unix */
121 if(!(src = malloc(filesize + 1))) {
122 fclose(fp);
123 return 0;
124 }
125 fread(src, 1, filesize, fp);
126 src[filesize] = 0;
127 fclose(fp);
129 fprintf(stderr, "compiling %s shader: %s... ", (sdr_type == GL_VERTEX_SHADER ? "vertex" : "pixel"), fname);
130 sdr = create_shader(src, sdr_type);
132 free(src);
133 return sdr;
134 }
137 unsigned int get_vertex_shader(const char *fname)
138 {
139 return get_shader(fname, GL_VERTEX_SHADER);
140 }
142 unsigned int get_pixel_shader(const char *fname)
143 {
144 return get_shader(fname, GL_FRAGMENT_SHADER);
145 }
147 unsigned int get_shader(const char *fname, unsigned int sdr_type)
148 {
149 unsigned int sdr;
150 #if 0
151 if((res = get_resource(sdrman, fname))) {
152 /* TODO: validate that the shader matches sdr_type? */
153 return (uintptr_t)res;
154 }
155 #endif
157 if(!(sdr = load_shader(fname, sdr_type))) {
158 return 0;
159 }
160 add_shader(fname, sdr);
161 return sdr;
162 }
164 int add_shader(const char *fname, unsigned int sdr)
165 {
166 return 0;/*add_resource(sdrman, fname, (void*)(uintptr_t)sdr);*/
167 }
169 int remove_shader(const char *fname)
170 {
171 return 0;/*remove_resource(sdrman, fname);*/
172 }
175 /* ---- gpu programs ---- */
177 unsigned int create_program(void)
178 {
179 unsigned int prog = glCreateProgram();
180 assert(glGetError() == GL_NO_ERROR);
181 return prog;
182 }
184 unsigned int create_program_link(unsigned int vs, unsigned int ps)
185 {
186 unsigned int prog;
187 if(!vs && !ps) {
188 return 0;
189 }
191 if(!(prog = create_program())) {
192 return 0;
193 }
195 if(vs) {
196 attach_shader(prog, vs);
197 assert(glGetError() == GL_NO_ERROR);
198 }
199 if(ps) {
200 attach_shader(prog, ps);
201 assert(glGetError() == GL_NO_ERROR);
202 }
204 if(link_program(prog) == -1) {
205 free_program(prog);
206 return 0;
207 }
208 return prog;
209 }
211 unsigned int create_program_load(const char *vfile, const char *pfile)
212 {
213 unsigned int vs = 0, ps = 0;
215 if(vfile) {
216 if(!(vs = get_vertex_shader(vfile))) {
217 return 0;
218 }
219 }
220 if(pfile) {
221 if(!(ps = get_pixel_shader(pfile))) {
222 return 0;
223 }
224 }
225 return create_program_link(vs, ps);
226 }
228 void free_program(unsigned int sdr)
229 {
230 glDeleteProgram(sdr);
231 }
233 void attach_shader(unsigned int prog, unsigned int sdr)
234 {
235 glAttachShader(prog, sdr);
236 assert(glGetError() == GL_NO_ERROR);
237 }
239 int link_program(unsigned int prog)
240 {
241 int linked, info_len, retval = 0;
242 char *info_str = 0;
244 glLinkProgram(prog);
245 assert(glGetError() == GL_NO_ERROR);
246 glGetProgramiv(prog, GL_LINK_STATUS, &linked);
247 assert(glGetError() == GL_NO_ERROR);
248 glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &info_len);
249 assert(glGetError() == GL_NO_ERROR);
251 if(info_len) {
252 if((info_str = malloc(info_len + 1))) {
253 glGetProgramInfoLog(prog, info_len, 0, info_str);
254 assert(glGetError() == GL_NO_ERROR);
255 }
256 }
258 if(linked) {
259 fprintf(stderr, info_str ? "linking done: %s\n" : "linking done\n", info_str);
260 } else {
261 fprintf(stderr, info_str ? "linking failed: %s\n" : "linking failed\n", info_str);
262 retval = -1;
263 }
265 free(info_str);
266 return retval;
267 }
269 int bind_program(unsigned int prog)
270 {
271 GLenum err;
273 glUseProgram(prog);
274 if(prog && (err = glGetError()) != GL_NO_ERROR) {
275 /* maybe the program is not linked, try to link first */
276 if(err == GL_INVALID_OPERATION) {
277 if(link_program(prog) == -1) {
278 return -1;
279 }
280 glUseProgram(prog);
281 return glGetError() == GL_NO_ERROR ? 0 : -1;
282 }
283 return -1;
284 }
285 return 0;
286 }
288 /* ugly but I'm not going to write the same bloody code over and over */
289 #define BEGIN_UNIFORM_CODE \
290 int loc, curr_prog; \
291 glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); \
292 if(curr_prog != prog && bind_program(prog) == -1) { \
293 return -1; \
294 } \
295 if((loc = glGetUniformLocation(prog, name)) != -1)
297 #define END_UNIFORM_CODE \
298 if(curr_prog != prog) { \
299 bind_program(curr_prog); \
300 } \
301 return loc == -1 ? -1 : 0
303 int set_uniform_int(unsigned int prog, const char *name, int val)
304 {
305 BEGIN_UNIFORM_CODE {
306 glUniform1i(loc, val);
307 }
308 END_UNIFORM_CODE;
309 }
311 int set_uniform_float(unsigned int prog, const char *name, float val)
312 {
313 BEGIN_UNIFORM_CODE {
314 glUniform1f(loc, val);
315 }
316 END_UNIFORM_CODE;
317 }