doorbell
changeset 0:a5755687dd75
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Tue, 08 Mar 2016 03:26:01 +0200 |
parents | |
children | daade2a35e69 d3f2a2b19504 |
files | .hgignore spycam/Makefile spycam/src/main.cc spycam/src/sdr.c spycam/src/sdr.h spycam/src/spycam.cc spycam/src/spycam.h |
diffstat | 7 files changed, 831 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/.hgignore Tue Mar 08 03:26:01 2016 +0200 1.3 @@ -0,0 +1,4 @@ 1.4 +\.o$ 1.5 +\.d$ 1.6 +\.swp$ 1.7 +spycam$
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/spycam/Makefile Tue Mar 08 03:26:01 2016 +0200 2.3 @@ -0,0 +1,19 @@ 2.4 +src = $(wildcard src/*.cc) 2.5 +csrc = $(wildcard src/*.c) 2.6 +obj = $(src:.cc=.o) $(csrc:.c=.o) 2.7 +bin = spycam 2.8 + 2.9 +warn = -pedantic -Wall 2.10 +opt = -O0 2.11 +dbg = -g 2.12 + 2.13 +CFLAGS = $(warn) $(opt) $(dbg) 2.14 +CXXFLAGS = $(warn) $(opt) $(dbg) 2.15 +LDFLAGS = -lX11 -lEGL -lGLESv2 -lm -lgmath 2.16 + 2.17 +$(bin): $(obj) 2.18 + $(CXX) -o $@ $(obj) $(LDFLAGS) 2.19 + 2.20 +.PHONY: clean 2.21 +clean: 2.22 + rm -f $(obj) $(bin)
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/spycam/src/main.cc Tue Mar 08 03:26:01 2016 +0200 3.3 @@ -0,0 +1,236 @@ 3.4 +#include <stdio.h> 3.5 +#include <stdlib.h> 3.6 +#include <unistd.h> 3.7 +#include <sys/select.h> 3.8 +#include <X11/Xlib.h> 3.9 +#include <X11/Xatom.h> 3.10 +#include <GLES2/gl2.h> 3.11 +#include <EGL/egl.h> 3.12 +#include "spycam.h" 3.13 + 3.14 +static void cleanup(); 3.15 +static bool create_glwin(int xsz, int ysz); 3.16 +static bool handle_event(XEvent *ev); 3.17 +static void set_window_title(const char *title); 3.18 + 3.19 +static int win_width, win_height; 3.20 +static bool quit, redraw_pending; 3.21 +static Display *dpy; 3.22 +static Window win; 3.23 +static EGLDisplay egl_dpy; 3.24 +static EGLContext egl_ctx; 3.25 +static EGLSurface egl_win; 3.26 +static Atom xa_wm_proto, xa_del_window; 3.27 + 3.28 +int main(int argc, char **argv) 3.29 +{ 3.30 + if(!(dpy = XOpenDisplay(0))) { 3.31 + fprintf(stderr, "failed to connect to the X server.\n"); 3.32 + return 1; 3.33 + } 3.34 + xa_wm_proto = XInternAtom(dpy, "WM_PROTOCOLS", False); 3.35 + xa_del_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False); 3.36 + 3.37 + egl_dpy = eglGetDisplay(dpy); 3.38 + int egl_ver_major, egl_ver_minor; 3.39 + if(!eglInitialize(egl_dpy, &egl_ver_major, &egl_ver_minor)) { 3.40 + fprintf(stderr, "failed to initialize EGL\n"); 3.41 + return 1; 3.42 + } 3.43 + printf("initialized EGL %d.%d\n", egl_ver_major, egl_ver_minor); 3.44 + 3.45 + if(!create_glwin(800, 600)) { 3.46 + cleanup(); 3.47 + return 1; 3.48 + } 3.49 + 3.50 + if(!app_init()) { 3.51 + cleanup(); 3.52 + return 1; 3.53 + } 3.54 + 3.55 + for(;;) { 3.56 + while(XPending(dpy) || !redraw_pending) { 3.57 + XEvent ev; 3.58 + XNextEvent(dpy, &ev); 3.59 + if(!handle_event(&ev) || quit) { 3.60 + goto break_main_loop; 3.61 + } 3.62 + } 3.63 + 3.64 + if(redraw_pending) { 3.65 + app_draw(); 3.66 + eglSwapBuffers(egl_dpy, egl_win); 3.67 + } 3.68 + } 3.69 +break_main_loop: 3.70 + 3.71 + cleanup(); 3.72 + return 0; 3.73 +} 3.74 + 3.75 +void app_quit() 3.76 +{ 3.77 + quit = true; 3.78 +} 3.79 + 3.80 +void app_redisplay() 3.81 +{ 3.82 + redraw_pending = true; 3.83 +} 3.84 + 3.85 +static void cleanup() 3.86 +{ 3.87 + if(egl_dpy) { 3.88 + eglMakeCurrent(egl_dpy, 0, 0, 0); 3.89 + if(egl_win) 3.90 + eglDestroySurface(egl_dpy, egl_win); 3.91 + if(egl_ctx) 3.92 + eglDestroyContext(egl_dpy, egl_ctx); 3.93 + eglTerminate(egl_dpy); 3.94 + } 3.95 + if(dpy) { 3.96 + if(win) 3.97 + XDestroyWindow(dpy, win); 3.98 + XCloseDisplay(dpy); 3.99 + } 3.100 +} 3.101 + 3.102 +static bool create_glwin(int xsz, int ysz) 3.103 +{ 3.104 + static const int egl_attr[] = { 3.105 + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 3.106 + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 3.107 + EGL_RED_SIZE, 5, 3.108 + EGL_GREEN_SIZE, 5, 3.109 + EGL_BLUE_SIZE, 5, 3.110 + EGL_DEPTH_SIZE, 16, 3.111 + EGL_NONE 3.112 + }; 3.113 + 3.114 + int scr = DefaultScreen(dpy); 3.115 + Window root_win = RootWindow(dpy, scr); 3.116 + 3.117 + EGLConfig cfg; 3.118 + int num_cfg; 3.119 + if(!eglChooseConfig(egl_dpy, egl_attr, &cfg, 1, &num_cfg)) { 3.120 + fprintf(stderr, "failed to find matching EGL visual\n"); 3.121 + return false; 3.122 + } 3.123 + int rsize, gsize, bsize, zsize, ssize, vis_id; 3.124 + eglGetConfigAttrib(egl_dpy, cfg, EGL_RED_SIZE, &rsize); 3.125 + eglGetConfigAttrib(egl_dpy, cfg, EGL_GREEN_SIZE, &gsize); 3.126 + eglGetConfigAttrib(egl_dpy, cfg, EGL_BLUE_SIZE, &bsize); 3.127 + eglGetConfigAttrib(egl_dpy, cfg, EGL_DEPTH_SIZE, &zsize); 3.128 + eglGetConfigAttrib(egl_dpy, cfg, EGL_STENCIL_SIZE, &ssize); 3.129 + eglGetConfigAttrib(egl_dpy, cfg, EGL_NATIVE_VISUAL_ID, &vis_id); 3.130 + printf("got visual %d: %d bpp (%d%d%d), %d zbuffer, %d stencil\n", vis_id, rsize + gsize + bsize, 3.131 + rsize, gsize, bsize, zsize, ssize); 3.132 + 3.133 + int num_vis; 3.134 + XVisualInfo *vis_info, vis_template; 3.135 + vis_template.visualid = vis_id; 3.136 + if(!(vis_info = XGetVisualInfo(dpy, VisualIDMask, &vis_template, &num_vis))) { 3.137 + fprintf(stderr, "visual id %d is invalid (?!)\n", vis_id); 3.138 + return false; 3.139 + } 3.140 + 3.141 + XSetWindowAttributes xattr; 3.142 + xattr.border_pixel = xattr.backing_pixel = BlackPixel(dpy, scr); 3.143 + xattr.colormap = XCreateColormap(dpy, root_win, vis_info->visual, AllocNone); 3.144 + unsigned int xattr_mask = CWColormap | CWBorderPixel | CWBackPixel; 3.145 + 3.146 + win = XCreateWindow(dpy, root_win, 0, 0, xsz, ysz, 0, vis_info->depth, InputOutput, 3.147 + vis_info->visual, xattr_mask, &xattr); 3.148 + if(!win) { 3.149 + fprintf(stderr, "failed to create window\n"); 3.150 + XFree(vis_info); 3.151 + return false; 3.152 + } 3.153 + XFree(vis_info); 3.154 + XSelectInput(dpy, win, ExposureMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask); 3.155 + 3.156 + XSetWMProtocols(dpy, win, &xa_del_window, 1); 3.157 + set_window_title("spycam"); 3.158 + 3.159 + eglBindAPI(EGL_OPENGL_ES_API); 3.160 + 3.161 + if(!(egl_win = eglCreateWindowSurface(egl_dpy, cfg, win, 0))) { 3.162 + fprintf(stderr, "failed to create EGL window\n"); 3.163 + XDestroyWindow(dpy, win); 3.164 + return false; 3.165 + } 3.166 + 3.167 + static const int ctxattr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; 3.168 + if(!(egl_ctx = eglCreateContext(egl_dpy, cfg, EGL_NO_CONTEXT, ctxattr))) { 3.169 + fprintf(stderr, "failed to create EGL context\n"); 3.170 + eglDestroySurface(egl_dpy, egl_win); 3.171 + XDestroyWindow(dpy, win); 3.172 + return false; 3.173 + } 3.174 + eglMakeCurrent(egl_dpy, egl_win, egl_win, egl_ctx); 3.175 + 3.176 + XMapWindow(dpy, win); 3.177 + 3.178 + eglQuerySurface(dpy, egl_win, EGL_WIDTH, &win_width); 3.179 + eglQuerySurface(dpy, egl_win, EGL_HEIGHT, &win_height); 3.180 + app_reshape(win_width, win_height); 3.181 + 3.182 + return true; 3.183 +} 3.184 + 3.185 +static bool handle_event(XEvent *ev) 3.186 +{ 3.187 + static bool mapped; 3.188 + 3.189 + switch(ev->type) { 3.190 + case Expose: 3.191 + if(mapped) { 3.192 + redraw_pending = true; 3.193 + } 3.194 + break; 3.195 + 3.196 + case MapNotify: 3.197 + mapped = true; 3.198 + redraw_pending = true; 3.199 + break; 3.200 + 3.201 + case UnmapNotify: 3.202 + mapped = false; 3.203 + redraw_pending = false; 3.204 + break; 3.205 + 3.206 + case ConfigureNotify: 3.207 + if(win_width != (int)ev->xconfigure.width || win_height != (int)ev->xconfigure.height) { 3.208 + win_width = ev->xconfigure.width; 3.209 + win_height = ev->xconfigure.height; 3.210 + app_reshape(win_width, win_height); 3.211 + } 3.212 + break; 3.213 + 3.214 + case KeyPress: 3.215 + case KeyRelease: 3.216 + app_keyboard(XLookupKeysym(&ev->xkey, 0) & 0xff, ev->type == KeyPress); 3.217 + break; 3.218 + 3.219 + case ClientMessage: 3.220 + if(ev->xclient.message_type == xa_wm_proto && 3.221 + (Atom)ev->xclient.data.l[0] == xa_del_window) { 3.222 + return false; 3.223 + } 3.224 + break; 3.225 + 3.226 + default: 3.227 + break; 3.228 + } 3.229 + return true; 3.230 +} 3.231 + 3.232 +static void set_window_title(const char *title) 3.233 +{ 3.234 + XTextProperty text_prop; 3.235 + XStringListToTextProperty((char**)&title, 1, &text_prop); 3.236 + XSetWMName(dpy, win, &text_prop); 3.237 + XSetWMIconName(dpy, win, &text_prop); 3.238 + XFree(text_prop.value); 3.239 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/spycam/src/sdr.c Tue Mar 08 03:26:01 2016 +0200 4.3 @@ -0,0 +1,407 @@ 4.4 +#include <stdio.h> 4.5 +#include <stdlib.h> 4.6 +#include <string.h> 4.7 +#include <errno.h> 4.8 +#include <stdarg.h> 4.9 +#include <assert.h> 4.10 +#include <GLES2/gl2.h> 4.11 + 4.12 +#if defined(unix) || defined(__unix__) 4.13 +#include <unistd.h> 4.14 +#include <sys/stat.h> 4.15 +#endif /* unix */ 4.16 + 4.17 +#include "sdr.h" 4.18 + 4.19 +static const char *sdrtypestr(unsigned int sdrtype); 4.20 + 4.21 +unsigned int create_vertex_shader(const char *src) 4.22 +{ 4.23 + return create_shader(src, GL_VERTEX_SHADER); 4.24 +} 4.25 + 4.26 +unsigned int create_pixel_shader(const char *src) 4.27 +{ 4.28 + return create_shader(src, GL_FRAGMENT_SHADER); 4.29 +} 4.30 + 4.31 +unsigned int create_tessctl_shader(const char *src) 4.32 +{ 4.33 +#ifdef GL_TESS_CONTROL_SHADER 4.34 + return create_shader(src, GL_TESS_CONTROL_SHADER); 4.35 +#else 4.36 + return 0; 4.37 +#endif 4.38 +} 4.39 + 4.40 +unsigned int create_tesseval_shader(const char *src) 4.41 +{ 4.42 +#ifdef GL_TESS_EVALUATION_SHADER 4.43 + return create_shader(src, GL_TESS_EVALUATION_SHADER); 4.44 +#else 4.45 + return 0; 4.46 +#endif 4.47 +} 4.48 + 4.49 +unsigned int create_geometry_shader(const char *src) 4.50 +{ 4.51 +#ifdef GL_GEOMETRY_SHADER 4.52 + return create_shader(src, GL_GEOMETRY_SHADER); 4.53 +#else 4.54 + return 0; 4.55 +#endif 4.56 +} 4.57 + 4.58 +unsigned int create_shader(const char *src, unsigned int sdr_type) 4.59 +{ 4.60 + unsigned int sdr; 4.61 + int success, info_len; 4.62 + char *info_str = 0; 4.63 + GLenum err; 4.64 + 4.65 + sdr = glCreateShader(sdr_type); 4.66 + assert(glGetError() == GL_NO_ERROR); 4.67 + glShaderSource(sdr, 1, &src, 0); 4.68 + err = glGetError(); 4.69 + assert(err == GL_NO_ERROR); 4.70 + glCompileShader(sdr); 4.71 + assert(glGetError() == GL_NO_ERROR); 4.72 + 4.73 + glGetShaderiv(sdr, GL_COMPILE_STATUS, &success); 4.74 + assert(glGetError() == GL_NO_ERROR); 4.75 + glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &info_len); 4.76 + assert(glGetError() == GL_NO_ERROR); 4.77 + 4.78 + if(info_len) { 4.79 + if((info_str = malloc(info_len + 1))) { 4.80 + glGetShaderInfoLog(sdr, info_len, 0, info_str); 4.81 + assert(glGetError() == GL_NO_ERROR); 4.82 + info_str[info_len] = 0; 4.83 + } 4.84 + } 4.85 + 4.86 + if(success) { 4.87 + fprintf(stderr, info_str ? "done: %s\n" : "done\n", info_str); 4.88 + } else { 4.89 + fprintf(stderr, info_str ? "failed: %s\n" : "failed\n", info_str); 4.90 + glDeleteShader(sdr); 4.91 + sdr = 0; 4.92 + } 4.93 + 4.94 + free(info_str); 4.95 + return sdr; 4.96 +} 4.97 + 4.98 +void free_shader(unsigned int sdr) 4.99 +{ 4.100 + glDeleteShader(sdr); 4.101 +} 4.102 + 4.103 +unsigned int load_vertex_shader(const char *fname) 4.104 +{ 4.105 + return load_shader(fname, GL_VERTEX_SHADER); 4.106 +} 4.107 + 4.108 +unsigned int load_pixel_shader(const char *fname) 4.109 +{ 4.110 + return load_shader(fname, GL_FRAGMENT_SHADER); 4.111 +} 4.112 + 4.113 +unsigned int load_tessctl_shader(const char *fname) 4.114 +{ 4.115 +#ifdef GL_TESS_CONTROL_SHADER 4.116 + return load_shader(fname, GL_TESS_CONTROL_SHADER); 4.117 +#else 4.118 + return 0; 4.119 +#endif 4.120 +} 4.121 + 4.122 +unsigned int load_tesseval_shader(const char *fname) 4.123 +{ 4.124 +#ifdef GL_TESS_EVALUATION_SHADER 4.125 + return load_shader(fname, GL_TESS_EVALUATION_SHADER); 4.126 +#else 4.127 + return 0; 4.128 +#endif 4.129 +} 4.130 + 4.131 +unsigned int load_geometry_shader(const char *fname) 4.132 +{ 4.133 +#ifdef GL_GEOMETRY_SHADER 4.134 + return load_shader(fname, GL_GEOMETRY_SHADER); 4.135 +#else 4.136 + return 0; 4.137 +#endif 4.138 +} 4.139 + 4.140 +unsigned int load_shader(const char *fname, unsigned int sdr_type) 4.141 +{ 4.142 + unsigned int sdr; 4.143 + size_t filesize; 4.144 + FILE *fp; 4.145 + char *src; 4.146 + 4.147 + if(!(fp = fopen(fname, "rb"))) { 4.148 + fprintf(stderr, "failed to open shader %s: %s\n", fname, strerror(errno)); 4.149 + return 0; 4.150 + } 4.151 + 4.152 + fseek(fp, 0, SEEK_END); 4.153 + filesize = ftell(fp); 4.154 + fseek(fp, 0, SEEK_SET); 4.155 + 4.156 + if(!(src = malloc(filesize + 1))) { 4.157 + fclose(fp); 4.158 + return 0; 4.159 + } 4.160 + fread(src, 1, filesize, fp); 4.161 + src[filesize] = 0; 4.162 + fclose(fp); 4.163 + 4.164 + fprintf(stderr, "compiling %s shader: %s... ", sdrtypestr(sdr_type), fname); 4.165 + sdr = create_shader(src, sdr_type); 4.166 + 4.167 + free(src); 4.168 + return sdr; 4.169 +} 4.170 + 4.171 + 4.172 +/* ---- gpu programs ---- */ 4.173 + 4.174 +unsigned int create_program(void) 4.175 +{ 4.176 + unsigned int prog = glCreateProgram(); 4.177 + assert(glGetError() == GL_NO_ERROR); 4.178 + return prog; 4.179 +} 4.180 + 4.181 +unsigned int create_program_link(unsigned int sdr0, ...) 4.182 +{ 4.183 + unsigned int prog, sdr; 4.184 + va_list ap; 4.185 + 4.186 + if(!(prog = create_program())) { 4.187 + return 0; 4.188 + } 4.189 + 4.190 + attach_shader(prog, sdr0); 4.191 + if(glGetError()) { 4.192 + return 0; 4.193 + } 4.194 + 4.195 + va_start(ap, sdr0); 4.196 + while((sdr = va_arg(ap, unsigned int))) { 4.197 + attach_shader(prog, sdr); 4.198 + if(glGetError()) { 4.199 + return 0; 4.200 + } 4.201 + } 4.202 + va_end(ap); 4.203 + 4.204 + if(link_program(prog) == -1) { 4.205 + free_program(prog); 4.206 + return 0; 4.207 + } 4.208 + return prog; 4.209 +} 4.210 + 4.211 +unsigned int create_program_load(const char *vfile, const char *pfile) 4.212 +{ 4.213 + unsigned int vs = 0, ps = 0; 4.214 + 4.215 + if(vfile && *vfile && !(vs = load_vertex_shader(vfile))) { 4.216 + return 0; 4.217 + } 4.218 + if(pfile && *pfile && !(ps = load_pixel_shader(pfile))) { 4.219 + return 0; 4.220 + } 4.221 + return create_program_link(vs, ps, 0); 4.222 +} 4.223 + 4.224 +void free_program(unsigned int sdr) 4.225 +{ 4.226 + glDeleteProgram(sdr); 4.227 +} 4.228 + 4.229 +void attach_shader(unsigned int prog, unsigned int sdr) 4.230 +{ 4.231 + int err; 4.232 + 4.233 + if(prog && sdr) { 4.234 + assert(glGetError() == GL_NO_ERROR); 4.235 + glAttachShader(prog, sdr); 4.236 + if((err = glGetError()) != GL_NO_ERROR) { 4.237 + fprintf(stderr, "failed to attach shader %u to program %u (err: 0x%x)\n", sdr, prog, err); 4.238 + abort(); 4.239 + } 4.240 + } 4.241 +} 4.242 + 4.243 +int link_program(unsigned int prog) 4.244 +{ 4.245 + int linked, info_len, retval = 0; 4.246 + char *info_str = 0; 4.247 + 4.248 + glLinkProgram(prog); 4.249 + assert(glGetError() == GL_NO_ERROR); 4.250 + glGetProgramiv(prog, GL_LINK_STATUS, &linked); 4.251 + assert(glGetError() == GL_NO_ERROR); 4.252 + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &info_len); 4.253 + assert(glGetError() == GL_NO_ERROR); 4.254 + 4.255 + if(info_len) { 4.256 + if((info_str = malloc(info_len + 1))) { 4.257 + glGetProgramInfoLog(prog, info_len, 0, info_str); 4.258 + assert(glGetError() == GL_NO_ERROR); 4.259 + info_str[info_len] = 0; 4.260 + } 4.261 + } 4.262 + 4.263 + if(linked) { 4.264 + fprintf(stderr, info_str ? "linking done: %s\n" : "linking done\n", info_str); 4.265 + } else { 4.266 + fprintf(stderr, info_str ? "linking failed: %s\n" : "linking failed\n", info_str); 4.267 + retval = -1; 4.268 + } 4.269 + 4.270 + free(info_str); 4.271 + return retval; 4.272 +} 4.273 + 4.274 +int bind_program(unsigned int prog) 4.275 +{ 4.276 + GLenum err; 4.277 + 4.278 + glUseProgram(prog); 4.279 + if(prog && (err = glGetError()) != GL_NO_ERROR) { 4.280 + /* maybe the program is not linked, try linking first */ 4.281 + if(err == GL_INVALID_OPERATION) { 4.282 + if(link_program(prog) == -1) { 4.283 + return -1; 4.284 + } 4.285 + glUseProgram(prog); 4.286 + return glGetError() == GL_NO_ERROR ? 0 : -1; 4.287 + } 4.288 + return -1; 4.289 + } 4.290 + return 0; 4.291 +} 4.292 + 4.293 +/* ugly but I'm not going to write the same bloody code over and over */ 4.294 +#define BEGIN_UNIFORM_CODE \ 4.295 + int loc, curr_prog; \ 4.296 + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); \ 4.297 + if((unsigned int)curr_prog != prog && bind_program(prog) == -1) { \ 4.298 + return -1; \ 4.299 + } \ 4.300 + if((loc = glGetUniformLocation(prog, name)) != -1) 4.301 + 4.302 +#define END_UNIFORM_CODE \ 4.303 + if((unsigned int)curr_prog != prog) { \ 4.304 + bind_program(curr_prog); \ 4.305 + } \ 4.306 + return loc == -1 ? -1 : 0 4.307 + 4.308 +int set_uniform_int(unsigned int prog, const char *name, int val) 4.309 +{ 4.310 + BEGIN_UNIFORM_CODE { 4.311 + glUniform1i(loc, val); 4.312 + } 4.313 + END_UNIFORM_CODE; 4.314 +} 4.315 + 4.316 +int set_uniform_float(unsigned int prog, const char *name, float val) 4.317 +{ 4.318 + BEGIN_UNIFORM_CODE { 4.319 + glUniform1f(loc, val); 4.320 + } 4.321 + END_UNIFORM_CODE; 4.322 +} 4.323 + 4.324 +int set_uniform_float2(unsigned int prog, const char *name, float x, float y) 4.325 +{ 4.326 + BEGIN_UNIFORM_CODE { 4.327 + glUniform2f(loc, x, y); 4.328 + } 4.329 + END_UNIFORM_CODE; 4.330 +} 4.331 + 4.332 +int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z) 4.333 +{ 4.334 + BEGIN_UNIFORM_CODE { 4.335 + glUniform3f(loc, x, y, z); 4.336 + } 4.337 + END_UNIFORM_CODE; 4.338 +} 4.339 + 4.340 +int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w) 4.341 +{ 4.342 + BEGIN_UNIFORM_CODE { 4.343 + glUniform4f(loc, x, y, z, w); 4.344 + } 4.345 + END_UNIFORM_CODE; 4.346 +} 4.347 + 4.348 +int set_uniform_matrix4(unsigned int prog, const char *name, float *mat) 4.349 +{ 4.350 + BEGIN_UNIFORM_CODE { 4.351 + glUniformMatrix4fv(loc, 1, GL_FALSE, mat); 4.352 + } 4.353 + END_UNIFORM_CODE; 4.354 +} 4.355 + 4.356 +int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat) 4.357 +{ 4.358 + BEGIN_UNIFORM_CODE { 4.359 + glUniformMatrix4fv(loc, 1, GL_TRUE, mat); 4.360 + } 4.361 + END_UNIFORM_CODE; 4.362 +} 4.363 + 4.364 +int get_attrib_loc(unsigned int prog, const char *name) 4.365 +{ 4.366 + int loc, curr_prog; 4.367 + 4.368 + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); 4.369 + if((unsigned int)curr_prog != prog && bind_program(prog) == -1) { 4.370 + return -1; 4.371 + } 4.372 + 4.373 + loc = glGetAttribLocation(prog, (char*)name); 4.374 + 4.375 + if((unsigned int)curr_prog != prog) { 4.376 + bind_program(curr_prog); 4.377 + } 4.378 + return loc; 4.379 +} 4.380 + 4.381 +void set_attrib_float3(int attr_loc, float x, float y, float z) 4.382 +{ 4.383 + glVertexAttrib3f(attr_loc, x, y, z); 4.384 +} 4.385 + 4.386 +static const char *sdrtypestr(unsigned int sdrtype) 4.387 +{ 4.388 + switch(sdrtype) { 4.389 + case GL_VERTEX_SHADER: 4.390 + return "vertex"; 4.391 + case GL_FRAGMENT_SHADER: 4.392 + return "pixel"; 4.393 +#ifdef GL_TESS_CONTROL_SHADER 4.394 + case GL_TESS_CONTROL_SHADER: 4.395 + return "tessellation control"; 4.396 +#endif 4.397 +#ifdef GL_TESS_EVALUATION_SHADER 4.398 + case GL_TESS_EVALUATION_SHADER: 4.399 + return "tessellation evaluation"; 4.400 +#endif 4.401 +#ifdef GL_GEOMETRY_SHADER 4.402 + case GL_GEOMETRY_SHADER: 4.403 + return "geometry"; 4.404 +#endif 4.405 + 4.406 + default: 4.407 + break; 4.408 + } 4.409 + return "<unknown>"; 4.410 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/spycam/src/sdr.h Tue Mar 08 03:26:01 2016 +0200 5.3 @@ -0,0 +1,52 @@ 5.4 +#ifndef SDR_H_ 5.5 +#define SDR_H_ 5.6 + 5.7 +#ifdef __cplusplus 5.8 +extern "C" { 5.9 +#endif /* __cplusplus */ 5.10 + 5.11 +/* ---- shaders ---- */ 5.12 +unsigned int create_vertex_shader(const char *src); 5.13 +unsigned int create_pixel_shader(const char *src); 5.14 +unsigned int create_tessctl_shader(const char *src); 5.15 +unsigned int create_tesseval_shader(const char *src); 5.16 +unsigned int create_geometry_shader(const char *src); 5.17 +unsigned int create_shader(const char *src, unsigned int sdr_type); 5.18 +void free_shader(unsigned int sdr); 5.19 + 5.20 +unsigned int load_vertex_shader(const char *fname); 5.21 +unsigned int load_pixel_shader(const char *fname); 5.22 +unsigned int load_tessctl_shader(const char *fname); 5.23 +unsigned int load_tesseval_shader(const char *fname); 5.24 +unsigned int load_geometry_shader(const char *fname); 5.25 +unsigned int load_shader(const char *src, unsigned int sdr_type); 5.26 + 5.27 +int add_shader(const char *fname, unsigned int sdr); 5.28 +int remove_shader(const char *fname); 5.29 + 5.30 +/* ---- gpu programs ---- */ 5.31 +unsigned int create_program(void); 5.32 +unsigned int create_program_link(unsigned int sdr0, ...); 5.33 +unsigned int create_program_load(const char *vfile, const char *pfile); 5.34 +void free_program(unsigned int sdr); 5.35 + 5.36 +void attach_shader(unsigned int prog, unsigned int sdr); 5.37 +int link_program(unsigned int prog); 5.38 +int bind_program(unsigned int prog); 5.39 + 5.40 +int set_uniform_int(unsigned int prog, const char *name, int val); 5.41 +int set_uniform_float(unsigned int prog, const char *name, float val); 5.42 +int set_uniform_float2(unsigned int prog, const char *name, float x, float y); 5.43 +int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z); 5.44 +int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w); 5.45 +int set_uniform_matrix4(unsigned int prog, const char *name, float *mat); 5.46 +int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat); 5.47 + 5.48 +int get_attrib_loc(unsigned int prog, const char *name); 5.49 +void set_attrib_float3(int attr_loc, float x, float y, float z); 5.50 + 5.51 +#ifdef __cplusplus 5.52 +} 5.53 +#endif /* __cplusplus */ 5.54 + 5.55 +#endif /* SDR_H_ */
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/spycam/src/spycam.cc Tue Mar 08 03:26:01 2016 +0200 6.3 @@ -0,0 +1,98 @@ 6.4 +#include <GLES2/gl2.h> 6.5 +#include <gmath/gmath.h> 6.6 +#include "spycam.h" 6.7 +#include "sdr.h" 6.8 + 6.9 +static unsigned int sdr_prog, tex; 6.10 +static Mat4 world_matrix, view_matrix, proj_matrix; 6.11 +static int win_width, win_height; 6.12 + 6.13 +bool app_init() 6.14 +{ 6.15 + glClearColor(0.2, 0.2, 0.2, 1); 6.16 + 6.17 + if(!(sdr_prog = create_program_load("sdr/vertex.glsl", "sdr/pixel.glsl"))) { 6.18 + fprintf(stderr, "failed to load shader program\n"); 6.19 + return false; 6.20 + } 6.21 + glUseProgram(sdr_prog); 6.22 + glBindAttribLocation(sdr_prog, 0, "a_vertex"); 6.23 + glBindAttribLocation(sdr_prog, 1, "a_texcoord"); 6.24 + 6.25 + unsigned char *pixels = new unsigned char[256 * 256 * 3]; 6.26 + unsigned char *pptr = pixels; 6.27 + for(int i=0; i<256; i++) { 6.28 + for(int j=0; j<256; j++) { 6.29 + bool chess = ((i >> 4) & 1) == ((j >> 4) & 1); 6.30 + *pptr++ = chess ? 255 : 64; 6.31 + *pptr++ = 128; 6.32 + *pptr++ = chess ? 64 : 255; 6.33 + } 6.34 + } 6.35 + 6.36 + glGenTextures(1, &tex); 6.37 + glBindTexture(GL_TEXTURE_2D, tex); 6.38 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 6.39 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 6.40 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels); 6.41 + glGenerateMipmap(GL_TEXTURE_2D); 6.42 + delete [] pixels; 6.43 + 6.44 + return true; 6.45 +} 6.46 + 6.47 +void app_cleanup() 6.48 +{ 6.49 +} 6.50 + 6.51 +void app_draw() 6.52 +{ 6.53 + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 6.54 + 6.55 + glUseProgram(sdr_prog); 6.56 + set_uniform_matrix4(sdr_prog, "world_mat", world_matrix[0]); 6.57 + set_uniform_matrix4(sdr_prog, "view_mat", view_matrix[0]); 6.58 + set_uniform_matrix4(sdr_prog, "proj_mat", proj_matrix[0]); 6.59 + 6.60 + glBindTexture(GL_TEXTURE_2D, tex); 6.61 + 6.62 + static const float quad_verts[] = {-1, -1, 1, -1, 1, 1, -1, 1}; 6.63 + static const float quad_texcoords[] = {0, 0, 1, 0, 1, 1, 0, 1}; 6.64 + static const unsigned int quad_idx[] = {0, 1, 2, 0, 2, 3}; 6.65 + 6.66 + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, quad_verts); 6.67 + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, quad_texcoords); 6.68 + glEnableVertexAttribArray(0); 6.69 + glEnableVertexAttribArray(1); 6.70 + 6.71 + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, quad_idx); 6.72 + 6.73 + glDisableVertexAttribArray(0); 6.74 + glDisableVertexAttribArray(1); 6.75 +} 6.76 + 6.77 +void app_reshape(int x, int y) 6.78 +{ 6.79 + win_width = x; 6.80 + win_height = y; 6.81 + glViewport(0, 0, x, y); 6.82 +} 6.83 + 6.84 +void app_keyboard(int key, bool press) 6.85 +{ 6.86 + if(press) { 6.87 + switch(key) { 6.88 + case 27: 6.89 + app_quit(); 6.90 + break; 6.91 + } 6.92 + } 6.93 +} 6.94 + 6.95 +void app_mouse_button(int bn, bool press, int x, int y) 6.96 +{ 6.97 +} 6.98 + 6.99 +void app_mouse_motion(int x, int y) 6.100 +{ 6.101 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/spycam/src/spycam.h Tue Mar 08 03:26:01 2016 +0200 7.3 @@ -0,0 +1,15 @@ 7.4 +#ifndef SPYCAM_H_ 7.5 +#define SPYCAM_H_ 7.6 + 7.7 +bool app_init(); 7.8 +void app_cleanup(); 7.9 +void app_draw(); 7.10 +void app_reshape(int x, int y); 7.11 +void app_keyboard(int key, bool press); 7.12 +void app_mouse_button(int bn, bool press, int x, int y); 7.13 +void app_mouse_motion(int x, int y); 7.14 + 7.15 +void app_quit(); 7.16 +void app_redisplay(); 7.17 + 7.18 +#endif /* SPYCAM_H_ */