3dphotoshoot
changeset 17:aef7f51f6397
resource loading works
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 10 Jun 2015 06:56:27 +0300 |
parents | c6952cc82cca |
children | dccbd7d65517 |
files | src/android/assman.c src/assman.h src/game.c src/rbtree.c src/rbtree.h src/sdr.c src/texture.c src/texture.h |
diffstat | 8 files changed, 867 insertions(+), 33 deletions(-) [+] |
line diff
1.1 --- a/src/android/assman.c Tue Jun 09 18:38:33 2015 +0300 1.2 +++ b/src/android/assman.c Wed Jun 10 06:56:27 2015 +0300 1.3 @@ -4,11 +4,39 @@ 1.4 #include "native_glue.h" 1.5 #include "amain.h" 1.6 1.7 -ass_file *ass_fopen(const char *fname) 1.8 +ass_file *ass_fopen(const char *fname, const char *mode) 1.9 { 1.10 AAsset *ass; 1.11 + unsigned int flags = 0; 1.12 + char prev = 0; 1.13 1.14 - if(!(ass = AAssetManager_open(app->activity->assetManager, fname, O_RDONLY))) { 1.15 + while(*mode) { 1.16 + switch(*mode) { 1.17 + case 'r': 1.18 + flags |= O_RDONLY; 1.19 + break; 1.20 + 1.21 + case 'w': 1.22 + flags |= O_WRONLY; 1.23 + break; 1.24 + 1.25 + case 'a': 1.26 + flags |= O_APPEND; 1.27 + break; 1.28 + 1.29 + case '+': 1.30 + if(prev == 'w' || prev == 'a') { 1.31 + flags |= O_CREAT; 1.32 + } 1.33 + break; 1.34 + 1.35 + default: 1.36 + break; 1.37 + } 1.38 + prev = *mode++; 1.39 + } 1.40 + 1.41 + if(!(ass = AAssetManager_open(app->activity->assetManager, fname, flags))) { 1.42 return 0; 1.43 } 1.44 return (ass_file*)ass;
2.1 --- a/src/assman.h Tue Jun 09 18:38:33 2015 +0300 2.2 +++ b/src/assman.h Wed Jun 10 06:56:27 2015 +0300 2.3 @@ -5,7 +5,7 @@ 2.4 2.5 typedef void ass_file; 2.6 2.7 -ass_file *ass_fopen(const char *fname); 2.8 +ass_file *ass_fopen(const char *fname, const char *mode); 2.9 void ass_fclose(ass_file *fp); 2.10 long ass_fseek(ass_file *fp, long offs, int whence); 2.11
3.1 --- a/src/game.c Tue Jun 09 18:38:33 2015 +0300 3.2 +++ b/src/game.c Wed Jun 10 06:56:27 2015 +0300 3.3 @@ -7,15 +7,19 @@ 3.4 #include "camera.h" 3.5 #include "sdr.h" 3.6 #include "sanegl.h" 3.7 +#include "texture.h" 3.8 3.9 -static void draw_quad(float hsz, float vsz); 3.10 +static void draw_quad(float hsz, float vsz, unsigned int sdr); 3.11 3.12 static int win_width, win_height; 3.13 static float win_aspect; 3.14 static int video_width, video_height; 3.15 static float video_aspect; 3.16 -static unsigned int sdrprog; 3.17 -static int aloc_vertex, aloc_texcoord, uloc_tex; 3.18 +static unsigned int sdrprog, sdrprog_test; 3.19 +static int uloc_tex, uloc_test_tex; 3.20 +static struct texture *test_tex; 3.21 + 3.22 +enum { ATTR_VERTEX, ATTR_TEXCOORD }; 3.23 3.24 static const char *vsdr_source = 3.25 "attribute vec4 attr_vertex, attr_texcoord;\n" 3.26 @@ -28,7 +32,7 @@ 3.27 "\ttex_coords = matrix_texture * attr_texcoord;\n" 3.28 "}\n"; 3.29 3.30 -static const char *psdr_source = 3.31 +static const char *psdr_cam_source = 3.32 "#extension GL_OES_EGL_image_external : require\n" 3.33 "precision mediump float;\n" 3.34 "uniform samplerExternalOES tex;\n" 3.35 @@ -39,12 +43,21 @@ 3.36 "\tgl_FragColor = vec4(texel.xyz, 1.0);\n" 3.37 "}\n"; 3.38 3.39 +static const char *psdr_tex_source = 3.40 + "precision mediump float;\n" 3.41 + "uniform sampler2D tex;\n" 3.42 + "varying vec4 tex_coords;\n" 3.43 + "void main()\n" 3.44 + "{\n" 3.45 + "\tvec4 texel = texture2D(tex, tex_coords.xy);\n" 3.46 + "\tgl_FragColor = texel;\n" 3.47 + "}\n"; 3.48 3.49 int game_init(void) 3.50 { 3.51 - unsigned int vsdr, psdr; 3.52 + unsigned int vsdr, psdr_cam, psdr_tex; 3.53 3.54 - glEnable(GL_DEPTH_TEST); 3.55 + //glEnable(GL_DEPTH_TEST); 3.56 glEnable(GL_CULL_FACE); 3.57 3.58 glClearColor(0.4, 0.4, 0.4, 1); 3.59 @@ -52,17 +65,36 @@ 3.60 if(!(vsdr = create_vertex_shader(vsdr_source))) 3.61 return -1; 3.62 assert(glGetError() == GL_NO_ERROR); 3.63 - if(!(psdr = create_pixel_shader(psdr_source))) 3.64 + if(!(psdr_cam = create_pixel_shader(psdr_cam_source))) 3.65 return -1; 3.66 assert(glGetError() == GL_NO_ERROR); 3.67 - if(!(sdrprog = create_program_link(vsdr, psdr))) { 3.68 + if(!(psdr_tex = create_pixel_shader(psdr_tex_source))) 3.69 + return -1; 3.70 + assert(glGetError() == GL_NO_ERROR); 3.71 + if(!(sdrprog = create_program_link(vsdr, psdr_cam, 0))) { 3.72 fprintf(stderr, "failed to create shader program\n"); 3.73 return -1; 3.74 } 3.75 + if(!(sdrprog_test = create_program_link(vsdr, psdr_tex, 0))) { 3.76 + fprintf(stderr, "failed to create test shader program\n"); 3.77 + return -1; 3.78 + } 3.79 + 3.80 glUseProgram(sdrprog); 3.81 - aloc_vertex = glGetAttribLocation(sdrprog, "attr_vertex"); 3.82 - aloc_texcoord = glGetAttribLocation(sdrprog, "attr_texcoord"); 3.83 + glBindAttribLocation(sdrprog, ATTR_VERTEX, "attr_vertex"); 3.84 + glBindAttribLocation(sdrprog, ATTR_TEXCOORD, "attr_texcoord"); 3.85 uloc_tex = glGetUniformLocation(sdrprog, "tex"); 3.86 + glLinkProgram(sdrprog); 3.87 + 3.88 + glUseProgram(sdrprog_test); 3.89 + glBindAttribLocation(sdrprog_test, ATTR_VERTEX, "attr_vertex"); 3.90 + glBindAttribLocation(sdrprog_test, ATTR_TEXCOORD, "attr_texcoord"); 3.91 + uloc_test_tex = glGetUniformLocation(sdrprog_test, "tex"); 3.92 + glLinkProgram(sdrprog_test); 3.93 + 3.94 + if(!(test_tex = get_texture("data/opengl.png"))) { 3.95 + return -1; 3.96 + } 3.97 3.98 cam_start_video(); 3.99 cam_video_size(&video_width, &video_height); 3.100 @@ -94,7 +126,6 @@ 3.101 3.102 //float tsec = (float)msec / 1000.0f; 3.103 3.104 - //glClearColor(sin(tsec * 10.0), cos(tsec * 10.0), -sin(tsec * 10.0), 1.0); 3.105 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 3.106 3.107 gl_matrix_mode(GL_MODELVIEW); 3.108 @@ -115,37 +146,50 @@ 3.109 xscale = video_aspect; 3.110 yscale = 1.0; 3.111 } 3.112 - draw_quad(xscale, yscale); 3.113 + draw_quad(xscale, yscale, sdrprog); 3.114 + 3.115 + gl_matrix_mode(GL_TEXTURE); 3.116 + gl_load_identity(); 3.117 + gl_translatef(0, 1, 0); 3.118 + gl_scalef(1, -1, 1); 3.119 + gl_matrix_mode(GL_MODELVIEW); 3.120 + gl_load_identity(); 3.121 + gl_scalef((float)test_tex->width / (float)test_tex->height, 1, 1); 3.122 + 3.123 + glUseProgram(sdrprog_test); 3.124 + glBindTexture(GL_TEXTURE_2D, test_tex->texid); 3.125 + if(uloc_test_tex >= 0) { 3.126 + glUniform1i(uloc_test_tex, 0); 3.127 + } 3.128 + 3.129 + glEnable(GL_BLEND); 3.130 + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 3.131 + 3.132 + draw_quad(0.5, 0.5, sdrprog_test); 3.133 + 3.134 + glDisable(GL_BLEND); 3.135 } 3.136 3.137 -static void draw_quad(float hsz, float vsz) 3.138 +static void draw_quad(float hsz, float vsz, unsigned int sdr) 3.139 { 3.140 static const float varr[] = {-1, -1, 1, -1, 1, 1, -1, 1}; 3.141 static const float tcarr[] = {0, 0, 1, 0, 1, 1, 0, 1}; 3.142 3.143 - if(aloc_vertex == -1) { 3.144 - return; 3.145 - } 3.146 - 3.147 gl_matrix_mode(GL_MODELVIEW); 3.148 gl_push_matrix(); 3.149 gl_scalef(hsz, vsz, 1); 3.150 3.151 - gl_apply_xform(sdrprog); 3.152 + gl_apply_xform(sdr); 3.153 3.154 - glEnableVertexAttribArray(aloc_vertex); 3.155 - glVertexAttribPointer(aloc_vertex, 2, GL_FLOAT, 0, 0, varr); 3.156 - if(aloc_texcoord != -1) { 3.157 - glEnableVertexAttribArray(aloc_texcoord); 3.158 - glVertexAttribPointer(aloc_texcoord, 2, GL_FLOAT, 0, 0, tcarr); 3.159 - } 3.160 + glEnableVertexAttribArray(ATTR_VERTEX); 3.161 + glEnableVertexAttribArray(ATTR_TEXCOORD); 3.162 + glVertexAttribPointer(ATTR_VERTEX, 2, GL_FLOAT, 0, 0, varr); 3.163 + glVertexAttribPointer(ATTR_TEXCOORD, 2, GL_FLOAT, 0, 0, tcarr); 3.164 3.165 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 3.166 3.167 - glDisableVertexAttribArray(aloc_vertex); 3.168 - if(aloc_texcoord != -1) { 3.169 - glDisableVertexAttribArray(aloc_texcoord); 3.170 - } 3.171 + glDisableVertexAttribArray(ATTR_VERTEX); 3.172 + glDisableVertexAttribArray(ATTR_TEXCOORD); 3.173 3.174 gl_pop_matrix(); 3.175 }
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/rbtree.c Wed Jun 10 06:56:27 2015 +0300 4.3 @@ -0,0 +1,501 @@ 4.4 +/* 4.5 +rbtree - simple balanced binary search tree (red-black tree) library. 4.6 +Copyright (C) 2011-2014 John Tsiombikas <nuclear@member.fsf.org> 4.7 + 4.8 +rbtree is free software, feel free to use, modify, and redistribute it, under 4.9 +the terms of the 3-clause BSD license. See COPYING for details. 4.10 + */ 4.11 +#include <stdio.h> 4.12 +#include <stdlib.h> 4.13 +#include <stdint.h> 4.14 +#include <string.h> 4.15 +#include "rbtree.h" 4.16 + 4.17 +#define INT2PTR(x) ((void*)(intptr_t)(x)) 4.18 +#define PTR2INT(x) ((int)(intptr_t)(x)) 4.19 + 4.20 +struct rbtree { 4.21 + struct rbnode *root; 4.22 + 4.23 + rb_alloc_func_t alloc; 4.24 + rb_free_func_t free; 4.25 + 4.26 + rb_cmp_func_t cmp; 4.27 + rb_del_func_t del; 4.28 + void *del_cls; 4.29 + 4.30 + struct rbnode *rstack, *iter; 4.31 +}; 4.32 + 4.33 +static int cmpaddr(const void *ap, const void *bp); 4.34 +static int cmpint(const void *ap, const void *bp); 4.35 + 4.36 +static int count_nodes(struct rbnode *node); 4.37 +static void del_tree(struct rbnode *node, void (*delfunc)(struct rbnode*, void*), void *cls); 4.38 +static struct rbnode *insert(struct rbtree *rb, struct rbnode *tree, void *key, void *data); 4.39 +static struct rbnode *delete(struct rbtree *rb, struct rbnode *tree, void *key); 4.40 +/*static struct rbnode *find(struct rbtree *rb, struct rbnode *node, void *key);*/ 4.41 +static void traverse(struct rbnode *node, void (*func)(struct rbnode*, void*), void *cls); 4.42 + 4.43 +struct rbtree *rb_create(rb_cmp_func_t cmp_func) 4.44 +{ 4.45 + struct rbtree *rb; 4.46 + 4.47 + if(!(rb = malloc(sizeof *rb))) { 4.48 + return 0; 4.49 + } 4.50 + if(rb_init(rb, cmp_func) == -1) { 4.51 + free(rb); 4.52 + return 0; 4.53 + } 4.54 + return rb; 4.55 +} 4.56 + 4.57 +void rb_free(struct rbtree *rb) 4.58 +{ 4.59 + rb_destroy(rb); 4.60 + free(rb); 4.61 +} 4.62 + 4.63 + 4.64 +int rb_init(struct rbtree *rb, rb_cmp_func_t cmp_func) 4.65 +{ 4.66 + memset(rb, 0, sizeof *rb); 4.67 + 4.68 + if(!cmp_func) { 4.69 + rb->cmp = cmpaddr; 4.70 + } else if(cmp_func == RB_KEY_INT) { 4.71 + rb->cmp = cmpint; 4.72 + } else if(cmp_func == RB_KEY_STRING) { 4.73 + rb->cmp = (rb_cmp_func_t)strcmp; 4.74 + } else { 4.75 + rb->cmp = cmp_func; 4.76 + } 4.77 + 4.78 + rb->alloc = malloc; 4.79 + rb->free = free; 4.80 + return 0; 4.81 +} 4.82 + 4.83 +void rb_destroy(struct rbtree *rb) 4.84 +{ 4.85 + del_tree(rb->root, rb->del, rb->del_cls); 4.86 +} 4.87 + 4.88 +void rb_set_allocator(struct rbtree *rb, rb_alloc_func_t alloc, rb_free_func_t free) 4.89 +{ 4.90 + rb->alloc = alloc; 4.91 + rb->free = free; 4.92 +} 4.93 + 4.94 + 4.95 +void rb_set_compare_func(struct rbtree *rb, rb_cmp_func_t func) 4.96 +{ 4.97 + rb->cmp = func; 4.98 +} 4.99 + 4.100 +void rb_set_delete_func(struct rbtree *rb, rb_del_func_t func, void *cls) 4.101 +{ 4.102 + rb->del = func; 4.103 + rb->del_cls = cls; 4.104 +} 4.105 + 4.106 + 4.107 +void rb_clear(struct rbtree *rb) 4.108 +{ 4.109 + del_tree(rb->root, rb->del, rb->del_cls); 4.110 + rb->root = 0; 4.111 +} 4.112 + 4.113 +int rb_copy(struct rbtree *dest, struct rbtree *src) 4.114 +{ 4.115 + struct rbnode *node; 4.116 + 4.117 + rb_clear(dest); 4.118 + rb_begin(src); 4.119 + while((node = rb_next(src))) { 4.120 + if(rb_insert(dest, node->key, node->data) == -1) { 4.121 + return -1; 4.122 + } 4.123 + } 4.124 + return 0; 4.125 +} 4.126 + 4.127 +int rb_size(struct rbtree *rb) 4.128 +{ 4.129 + return count_nodes(rb->root); 4.130 +} 4.131 + 4.132 +int rb_insert(struct rbtree *rb, void *key, void *data) 4.133 +{ 4.134 + rb->root = insert(rb, rb->root, key, data); 4.135 + rb->root->red = 0; 4.136 + return 0; 4.137 +} 4.138 + 4.139 +int rb_inserti(struct rbtree *rb, int key, void *data) 4.140 +{ 4.141 + rb->root = insert(rb, rb->root, INT2PTR(key), data); 4.142 + rb->root->red = 0; 4.143 + return 0; 4.144 +} 4.145 + 4.146 + 4.147 +int rb_delete(struct rbtree *rb, void *key) 4.148 +{ 4.149 + rb->root = delete(rb, rb->root, key); 4.150 + rb->root->red = 0; 4.151 + return 0; 4.152 +} 4.153 + 4.154 +int rb_deletei(struct rbtree *rb, int key) 4.155 +{ 4.156 + rb->root = delete(rb, rb->root, INT2PTR(key)); 4.157 + rb->root->red = 0; 4.158 + return 0; 4.159 +} 4.160 + 4.161 + 4.162 +struct rbnode *rb_find(struct rbtree *rb, void *key) 4.163 +{ 4.164 + struct rbnode *node = rb->root; 4.165 + 4.166 + while(node) { 4.167 + int cmp = rb->cmp(key, node->key); 4.168 + if(cmp == 0) { 4.169 + return node; 4.170 + } 4.171 + node = cmp < 0 ? node->left : node->right; 4.172 + } 4.173 + return 0; 4.174 +} 4.175 + 4.176 +struct rbnode *rb_findi(struct rbtree *rb, int key) 4.177 +{ 4.178 + return rb_find(rb, INT2PTR(key)); 4.179 +} 4.180 + 4.181 + 4.182 +void rb_foreach(struct rbtree *rb, void (*func)(struct rbnode*, void*), void *cls) 4.183 +{ 4.184 + traverse(rb->root, func, cls); 4.185 +} 4.186 + 4.187 + 4.188 +struct rbnode *rb_root(struct rbtree *rb) 4.189 +{ 4.190 + return rb->root; 4.191 +} 4.192 + 4.193 +void rb_begin(struct rbtree *rb) 4.194 +{ 4.195 + rb->rstack = 0; 4.196 + rb->iter = rb->root; 4.197 +} 4.198 + 4.199 +#define push(sp, x) ((x)->next = (sp), (sp) = (x)) 4.200 +#define pop(sp) ((sp) = (sp)->next) 4.201 +#define top(sp) (sp) 4.202 + 4.203 +struct rbnode *rb_next(struct rbtree *rb) 4.204 +{ 4.205 + struct rbnode *res = 0; 4.206 + 4.207 + while(rb->rstack || rb->iter) { 4.208 + if(rb->iter) { 4.209 + push(rb->rstack, rb->iter); 4.210 + rb->iter = rb->iter->left; 4.211 + } else { 4.212 + rb->iter = top(rb->rstack); 4.213 + pop(rb->rstack); 4.214 + res = rb->iter; 4.215 + rb->iter = rb->iter->right; 4.216 + break; 4.217 + } 4.218 + } 4.219 + return res; 4.220 +} 4.221 + 4.222 +void *rb_node_key(struct rbnode *node) 4.223 +{ 4.224 + return node ? node->key : 0; 4.225 +} 4.226 + 4.227 +int rb_node_keyi(struct rbnode *node) 4.228 +{ 4.229 + return node ? PTR2INT(node->key) : 0; 4.230 +} 4.231 + 4.232 +void *rb_node_data(struct rbnode *node) 4.233 +{ 4.234 + return node ? node->data : 0; 4.235 +} 4.236 + 4.237 +static int cmpaddr(const void *ap, const void *bp) 4.238 +{ 4.239 + return ap < bp ? -1 : (ap > bp ? 1 : 0); 4.240 +} 4.241 + 4.242 +static int cmpint(const void *ap, const void *bp) 4.243 +{ 4.244 + return PTR2INT(ap) - PTR2INT(bp); 4.245 +} 4.246 + 4.247 + 4.248 +/* ---- left-leaning 2-3 red-black implementation ---- */ 4.249 + 4.250 +/* helper prototypes */ 4.251 +static int is_red(struct rbnode *tree); 4.252 +static void color_flip(struct rbnode *tree); 4.253 +static struct rbnode *rot_left(struct rbnode *a); 4.254 +static struct rbnode *rot_right(struct rbnode *a); 4.255 +static struct rbnode *find_min(struct rbnode *tree); 4.256 +static struct rbnode *del_min(struct rbtree *rb, struct rbnode *tree); 4.257 +/*static struct rbnode *move_red_right(struct rbnode *tree);*/ 4.258 +static struct rbnode *move_red_left(struct rbnode *tree); 4.259 +static struct rbnode *fix_up(struct rbnode *tree); 4.260 + 4.261 +static int count_nodes(struct rbnode *node) 4.262 +{ 4.263 + if(!node) 4.264 + return 0; 4.265 + 4.266 + return 1 + count_nodes(node->left) + count_nodes(node->right); 4.267 +} 4.268 + 4.269 +static void del_tree(struct rbnode *node, rb_del_func_t delfunc, void *cls) 4.270 +{ 4.271 + if(!node) 4.272 + return; 4.273 + 4.274 + del_tree(node->left, delfunc, cls); 4.275 + del_tree(node->right, delfunc, cls); 4.276 + 4.277 + if(delfunc) { 4.278 + delfunc(node, cls); 4.279 + } 4.280 + free(node); 4.281 +} 4.282 + 4.283 +static struct rbnode *insert(struct rbtree *rb, struct rbnode *tree, void *key, void *data) 4.284 +{ 4.285 + int cmp; 4.286 + 4.287 + if(!tree) { 4.288 + struct rbnode *node = rb->alloc(sizeof *node); 4.289 + node->red = 1; 4.290 + node->key = key; 4.291 + node->data = data; 4.292 + node->left = node->right = 0; 4.293 + return node; 4.294 + } 4.295 + 4.296 + cmp = rb->cmp(key, tree->key); 4.297 + 4.298 + if(cmp < 0) { 4.299 + tree->left = insert(rb, tree->left, key, data); 4.300 + } else if(cmp > 0) { 4.301 + tree->right = insert(rb, tree->right, key, data); 4.302 + } else { 4.303 + tree->data = data; 4.304 + } 4.305 + 4.306 + /* fix right-leaning reds */ 4.307 + if(is_red(tree->right)) { 4.308 + tree = rot_left(tree); 4.309 + } 4.310 + /* fix two reds in a row */ 4.311 + if(is_red(tree->left) && is_red(tree->left->left)) { 4.312 + tree = rot_right(tree); 4.313 + } 4.314 + 4.315 + /* if 4-node, split it by color inversion */ 4.316 + if(is_red(tree->left) && is_red(tree->right)) { 4.317 + color_flip(tree); 4.318 + } 4.319 + 4.320 + return tree; 4.321 +} 4.322 + 4.323 +static struct rbnode *delete(struct rbtree *rb, struct rbnode *tree, void *key) 4.324 +{ 4.325 + int cmp; 4.326 + 4.327 + if(!tree) { 4.328 + return 0; 4.329 + } 4.330 + 4.331 + cmp = rb->cmp(key, tree->key); 4.332 + 4.333 + if(cmp < 0) { 4.334 + if(!is_red(tree->left) && !is_red(tree->left->left)) { 4.335 + tree = move_red_left(tree); 4.336 + } 4.337 + tree->left = delete(rb, tree->left, key); 4.338 + } else { 4.339 + /* need reds on the right */ 4.340 + if(is_red(tree->left)) { 4.341 + tree = rot_right(tree); 4.342 + } 4.343 + 4.344 + /* found it at the bottom (XXX what certifies left is null?) */ 4.345 + if(cmp == 0 && !tree->right) { 4.346 + if(rb->del) { 4.347 + rb->del(tree, rb->del_cls); 4.348 + } 4.349 + rb->free(tree); 4.350 + return 0; 4.351 + } 4.352 + 4.353 + if(!is_red(tree->right) && !is_red(tree->right->left)) { 4.354 + tree = move_red_left(tree); 4.355 + } 4.356 + 4.357 + if(key == tree->key) { 4.358 + struct rbnode *rmin = find_min(tree->right); 4.359 + tree->key = rmin->key; 4.360 + tree->data = rmin->data; 4.361 + tree->right = del_min(rb, tree->right); 4.362 + } else { 4.363 + tree->right = delete(rb, tree->right, key); 4.364 + } 4.365 + } 4.366 + 4.367 + return fix_up(tree); 4.368 +} 4.369 + 4.370 +/*static struct rbnode *find(struct rbtree *rb, struct rbnode *node, void *key) 4.371 +{ 4.372 + int cmp; 4.373 + 4.374 + if(!node) 4.375 + return 0; 4.376 + 4.377 + if((cmp = rb->cmp(key, node->key)) == 0) { 4.378 + return node; 4.379 + } 4.380 + return find(rb, cmp < 0 ? node->left : node->right, key); 4.381 +}*/ 4.382 + 4.383 +static void traverse(struct rbnode *node, void (*func)(struct rbnode*, void*), void *cls) 4.384 +{ 4.385 + if(!node) 4.386 + return; 4.387 + 4.388 + traverse(node->left, func, cls); 4.389 + func(node, cls); 4.390 + traverse(node->right, func, cls); 4.391 +} 4.392 + 4.393 +/* helpers */ 4.394 + 4.395 +static int is_red(struct rbnode *tree) 4.396 +{ 4.397 + return tree && tree->red; 4.398 +} 4.399 + 4.400 +static void color_flip(struct rbnode *tree) 4.401 +{ 4.402 + tree->red = !tree->red; 4.403 + tree->left->red = !tree->left->red; 4.404 + tree->right->red = !tree->right->red; 4.405 +} 4.406 + 4.407 +static struct rbnode *rot_left(struct rbnode *a) 4.408 +{ 4.409 + struct rbnode *b = a->right; 4.410 + a->right = b->left; 4.411 + b->left = a; 4.412 + b->red = a->red; 4.413 + a->red = 1; 4.414 + return b; 4.415 +} 4.416 + 4.417 +static struct rbnode *rot_right(struct rbnode *a) 4.418 +{ 4.419 + struct rbnode *b = a->left; 4.420 + a->left = b->right; 4.421 + b->right = a; 4.422 + b->red = a->red; 4.423 + a->red = 1; 4.424 + return b; 4.425 +} 4.426 + 4.427 +static struct rbnode *find_min(struct rbnode *tree) 4.428 +{ 4.429 + if(!tree) 4.430 + return 0; 4.431 + 4.432 + while(tree->left) { 4.433 + tree = tree->left; 4.434 + } 4.435 + return tree; 4.436 +} 4.437 + 4.438 +static struct rbnode *del_min(struct rbtree *rb, struct rbnode *tree) 4.439 +{ 4.440 + if(!tree->left) { 4.441 + if(rb->del) { 4.442 + rb->del(tree->left, rb->del_cls); 4.443 + } 4.444 + rb->free(tree->left); 4.445 + return 0; 4.446 + } 4.447 + 4.448 + /* make sure we've got red (3/4-nodes) at the left side so we can delete at the bottom */ 4.449 + if(!is_red(tree->left) && !is_red(tree->left->left)) { 4.450 + tree = move_red_left(tree); 4.451 + } 4.452 + tree->left = del_min(rb, tree->left); 4.453 + 4.454 + /* fix right-reds, red-reds, and split 4-nodes on the way up */ 4.455 + return fix_up(tree); 4.456 +} 4.457 + 4.458 +#if 0 4.459 +/* push a red link on this node to the right */ 4.460 +static struct rbnode *move_red_right(struct rbnode *tree) 4.461 +{ 4.462 + /* flipping it makes both children go red, so we have a red to the right */ 4.463 + color_flip(tree); 4.464 + 4.465 + /* if after the flip we've got a red-red situation to the left, fix it */ 4.466 + if(is_red(tree->left->left)) { 4.467 + tree = rot_right(tree); 4.468 + color_flip(tree); 4.469 + } 4.470 + return tree; 4.471 +} 4.472 +#endif 4.473 + 4.474 +/* push a red link on this node to the left */ 4.475 +static struct rbnode *move_red_left(struct rbnode *tree) 4.476 +{ 4.477 + /* flipping it makes both children go red, so we have a red to the left */ 4.478 + color_flip(tree); 4.479 + 4.480 + /* if after the flip we've got a red-red on the right-left, fix it */ 4.481 + if(is_red(tree->right->left)) { 4.482 + tree->right = rot_right(tree->right); 4.483 + tree = rot_left(tree); 4.484 + color_flip(tree); 4.485 + } 4.486 + return tree; 4.487 +} 4.488 + 4.489 +static struct rbnode *fix_up(struct rbnode *tree) 4.490 +{ 4.491 + /* fix right-leaning */ 4.492 + if(is_red(tree->right)) { 4.493 + tree = rot_left(tree); 4.494 + } 4.495 + /* change invalid red-red pairs into a proper 4-node */ 4.496 + if(is_red(tree->left) && is_red(tree->left->left)) { 4.497 + tree = rot_right(tree); 4.498 + } 4.499 + /* split 4-nodes */ 4.500 + if(is_red(tree->left) && is_red(tree->right)) { 4.501 + color_flip(tree); 4.502 + } 4.503 + return tree; 4.504 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/rbtree.h Wed Jun 10 06:56:27 2015 +0300 5.3 @@ -0,0 +1,78 @@ 5.4 +/* 5.5 +rbtree - simple balanced binary search tree (red-black tree) library. 5.6 +Copyright (C) 2011-2014 John Tsiombikas <nuclear@member.fsf.org> 5.7 + 5.8 +rbtree is free software, feel free to use, modify, and redistribute it, under 5.9 +the terms of the 3-clause BSD license. See COPYING for details. 5.10 + */ 5.11 +#ifndef RBTREE_H_ 5.12 +#define RBTREE_H_ 5.13 + 5.14 +struct rbtree; 5.15 + 5.16 + 5.17 +struct rbnode { 5.18 + void *key, *data; 5.19 + int red; 5.20 + struct rbnode *left, *right; 5.21 + struct rbnode *next; /* for iterator stack */ 5.22 +}; 5.23 + 5.24 + 5.25 +typedef void *(*rb_alloc_func_t)(size_t); 5.26 +typedef void (*rb_free_func_t)(void*); 5.27 + 5.28 +typedef int (*rb_cmp_func_t)(const void*, const void*); 5.29 +typedef void (*rb_del_func_t)(struct rbnode*, void*); 5.30 + 5.31 +#define RB_KEY_ADDR (rb_cmp_func_t)(0) 5.32 +#define RB_KEY_INT (rb_cmp_func_t)(1) 5.33 +#define RB_KEY_STRING (rb_cmp_func_t)(3) 5.34 + 5.35 + 5.36 +#ifdef __cplusplus 5.37 +extern "C" { 5.38 +#endif 5.39 + 5.40 +struct rbtree *rb_create(rb_cmp_func_t cmp_func); 5.41 +void rb_free(struct rbtree *rb); 5.42 + 5.43 +int rb_init(struct rbtree *rb, rb_cmp_func_t cmp_func); 5.44 +void rb_destroy(struct rbtree *rb); 5.45 + 5.46 +void rb_set_allocator(struct rbtree *rb, rb_alloc_func_t alloc, rb_free_func_t free); 5.47 +void rb_set_compare_func(struct rbtree *rb, rb_cmp_func_t func); 5.48 +void rb_set_delete_func(struct rbtree *rb, rb_del_func_t func, void *cls); 5.49 +/* TODO add user deep copy function */ 5.50 + 5.51 +void rb_clear(struct rbtree *rb); 5.52 +int rb_copy(struct rbtree *dest, struct rbtree *src); 5.53 + 5.54 +int rb_size(struct rbtree *rb); 5.55 + 5.56 +int rb_insert(struct rbtree *rb, void *key, void *data); 5.57 +int rb_inserti(struct rbtree *rb, int key, void *data); 5.58 + 5.59 +int rb_delete(struct rbtree *rb, void *key); 5.60 +int rb_deletei(struct rbtree *rb, int key); 5.61 + 5.62 +struct rbnode *rb_find(struct rbtree *rb, void *key); 5.63 +struct rbnode *rb_findi(struct rbtree *rb, int key); 5.64 + 5.65 +void rb_foreach(struct rbtree *rb, void (*func)(struct rbnode*, void*), void *cls); 5.66 + 5.67 +struct rbnode *rb_root(struct rbtree *rb); 5.68 + 5.69 +void rb_begin(struct rbtree *rb); 5.70 +struct rbnode *rb_next(struct rbtree *rb); 5.71 + 5.72 +void *rb_node_key(struct rbnode *node); 5.73 +int rb_node_keyi(struct rbnode *node); 5.74 +void *rb_node_data(struct rbnode *node); 5.75 + 5.76 +#ifdef __cplusplus 5.77 +} 5.78 +#endif 5.79 + 5.80 + 5.81 +#endif /* RBTREE_H_ */
6.1 --- a/src/sdr.c Tue Jun 09 18:38:33 2015 +0300 6.2 +++ b/src/sdr.c Wed Jun 10 06:56:27 2015 +0300 6.3 @@ -233,10 +233,13 @@ 6.4 6.5 void attach_shader(unsigned int prog, unsigned int sdr) 6.6 { 6.7 + int err; 6.8 + 6.9 if(prog && sdr) { 6.10 + assert(glGetError() == GL_NO_ERROR); 6.11 glAttachShader(prog, sdr); 6.12 - if(glGetError() != GL_NO_ERROR) { 6.13 - fprintf(stderr, "failed to attach shader %u to program %u\n", sdr, prog); 6.14 + if((err = glGetError()) != GL_NO_ERROR) { 6.15 + fprintf(stderr, "failed to attach shader %u to program %u (err: 0x%x)\n", sdr, prog, err); 6.16 abort(); 6.17 } 6.18 }
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/src/texture.c Wed Jun 10 06:56:27 2015 +0300 7.3 @@ -0,0 +1,165 @@ 7.4 +#include <stdio.h> 7.5 +#include <stdlib.h> 7.6 +#include <string.h> 7.7 +#include <errno.h> 7.8 +#include <assert.h> 7.9 +#include "opengl.h" 7.10 +#include "texture.h" 7.11 +#include "imago2.h" 7.12 +#include "rbtree.h" 7.13 +#include "assman.h" 7.14 + 7.15 +static size_t ioread(void *buf, size_t bytes, void *uptr); 7.16 +static long ioseek(long offs, int whence, void *uptr); 7.17 +static unsigned int next_pow2(unsigned int x); 7.18 + 7.19 +static struct rbtree *texdb; 7.20 + 7.21 +int load_texture(struct texture *tex, const char *fname) 7.22 +{ 7.23 + struct img_pixmap img; 7.24 + struct img_io io; 7.25 + ass_file *fp; 7.26 + 7.27 + printf("loading texture: %s\n", fname); 7.28 + 7.29 + if(!(fp = ass_fopen(fname, "rb"))) { 7.30 + fprintf(stderr, "failed to open texture file: %s: %s\n", fname, strerror(errno)); 7.31 + return -1; 7.32 + } 7.33 + io.uptr = fp; 7.34 + io.read = ioread; 7.35 + io.write = 0; 7.36 + io.seek = ioseek; 7.37 + 7.38 + img_init(&img); 7.39 + if(img_read(&img, &io) == -1) { 7.40 + fprintf(stderr, "failed to load texture file: %s\n", fname); 7.41 + ass_fclose(fp); 7.42 + return -1; 7.43 + } 7.44 + img_convert(&img, IMG_FMT_RGBA32); 7.45 + 7.46 + tex->img_width = img.width; 7.47 + tex->img_height = img.height; 7.48 + tex->width = next_pow2(img.width); 7.49 + tex->height = next_pow2(img.height); 7.50 + 7.51 + printf(" %dx%d (tex: %dx%d)\n", tex->img_width, tex->img_height, tex->width, tex->height); 7.52 + 7.53 + glGenTextures(1, &tex->texid); 7.54 + glBindTexture(GL_TEXTURE_2D, tex->texid); 7.55 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 7.56 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 7.57 + 7.58 +#ifdef __GLEW_H__ 7.59 + if(GLEW_SGIS_generate_mipmap) { 7.60 + glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); 7.61 +#endif 7.62 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex->width, tex->height, 0, 7.63 + GL_RGBA, GL_UNSIGNED_BYTE, img.pixels); 7.64 +#ifdef __GLEW_H__ 7.65 + } else { 7.66 + gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, tex->width, tex->height, 7.67 + GL_RGBA, GL_UNSIGNED_BYTE, img.pixels); 7.68 + } 7.69 +#endif 7.70 + 7.71 +#ifdef GL_ES_VERSION_2_0 7.72 + glGenerateMipmap(GL_TEXTURE_2D); 7.73 +#endif 7.74 + 7.75 + return 0; 7.76 +} 7.77 + 7.78 +struct texture *get_texture(const char *fname) 7.79 +{ 7.80 + struct texture *tex; 7.81 + struct rbnode *node; 7.82 + 7.83 + if(!(texdb = rb_create(RB_KEY_STRING))) { 7.84 + static int err_printed; 7.85 + if(!err_printed) { 7.86 + fprintf(stderr, "failed to create texture database\n"); 7.87 + err_printed = 1; 7.88 + } 7.89 + return 0; 7.90 + } 7.91 + 7.92 + if((node = rb_find(texdb, (void*)fname))) { 7.93 + return rb_node_data(node); 7.94 + } 7.95 + 7.96 + if(!(tex = malloc(sizeof *tex))) { 7.97 + fprintf(stderr, "failed to load texture \"%s\": %s\n", fname, strerror(errno)); 7.98 + return 0; 7.99 + } 7.100 + if(load_texture(tex, fname) == -1) { 7.101 + free(tex); 7.102 + return 0; 7.103 + } 7.104 + 7.105 + if(rb_insert(texdb, (void*)fname, tex) == -1) { 7.106 + fprintf(stderr, "failed to insert texture into the texture database\n"); 7.107 + } 7.108 + return tex; 7.109 +} 7.110 + 7.111 + 7.112 +#define DBG_TEX_SZ 64 7.113 +int gen_debug_texture(struct texture *tex) 7.114 +{ 7.115 + static unsigned char *pixels; 7.116 + 7.117 + if(!pixels) { 7.118 + int i, j; 7.119 + unsigned char *pptr; 7.120 + pptr = pixels = malloc(DBG_TEX_SZ * DBG_TEX_SZ * 4); 7.121 + assert(pixels); 7.122 + 7.123 + for(i=0; i<DBG_TEX_SZ; i++) { 7.124 + for(j=0; j<DBG_TEX_SZ; j++) { 7.125 + int chess = ((j >> 3) & 1) == ((i >> 3) & 1); 7.126 + *pptr++ = chess ? 255 : 64; 7.127 + *pptr++ = 128; 7.128 + *pptr++ = chess ? 64 : 255; 7.129 + *pptr++ = 255; /* alpha */ 7.130 + } 7.131 + } 7.132 + } 7.133 + 7.134 + if(!tex->texid) { 7.135 + glGenTextures(1, &tex->texid); 7.136 + } 7.137 + 7.138 + glBindTexture(GL_TEXTURE_2D, tex->texid); 7.139 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 7.140 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 7.141 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, DBG_TEX_SZ, DBG_TEX_SZ, 0, GL_RGBA, 7.142 + GL_UNSIGNED_BYTE, pixels); 7.143 + 7.144 + tex->width = tex->img_width = tex->height = tex->img_height = DBG_TEX_SZ; 7.145 + return 0; 7.146 +} 7.147 + 7.148 + 7.149 +static size_t ioread(void *buf, size_t bytes, void *uptr) 7.150 +{ 7.151 + return ass_fread(buf, 1, bytes, uptr); 7.152 +} 7.153 + 7.154 +static long ioseek(long offs, int whence, void *uptr) 7.155 +{ 7.156 + return ass_fseek(uptr, offs, whence); 7.157 +} 7.158 + 7.159 +static unsigned int next_pow2(unsigned int x) 7.160 +{ 7.161 + x--; 7.162 + x = (x >> 1) | x; 7.163 + x = (x >> 2) | x; 7.164 + x = (x >> 4) | x; 7.165 + x = (x >> 8) | x; 7.166 + x = (x >> 16) | x; 7.167 + return x + 1; 7.168 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/src/texture.h Wed Jun 10 06:56:27 2015 +0300 8.3 @@ -0,0 +1,15 @@ 8.4 +#ifndef TEXTURE_H_ 8.5 +#define TEXTURE_H_ 8.6 + 8.7 +struct texture { 8.8 + unsigned int texid; 8.9 + int width, height; 8.10 + int img_width, img_height; /* in case we have a smaller image in a pow2 texture */ 8.11 +}; 8.12 + 8.13 +int load_texture(struct texture *tex, const char *fname); 8.14 +struct texture *get_texture(const char *fname); 8.15 + 8.16 +int gen_debug_texture(struct texture *tex); 8.17 + 8.18 +#endif /* TEXTURE_H_ */