libresman
changeset 11:bebc065a941f
doesn't work yet
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Fri, 07 Feb 2014 07:50:02 +0200 |
parents | 4d18498a0078 |
children | 84f55eab27cb |
files | examples/imgthumbs/.clang_complete examples/imgthumbs/Makefile examples/imgthumbs/src/main.c examples/imgthumbs/src/thumbs.c examples/imgthumbs/src/thumbs.h src/resman.c src/resman.h src/threadpool.c |
diffstat | 8 files changed, 165 insertions(+), 39 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/examples/imgthumbs/.clang_complete Fri Feb 07 07:50:02 2014 +0200 1.3 @@ -0,0 +1,1 @@ 1.4 +-I../../src
2.1 --- a/examples/imgthumbs/Makefile Wed Feb 05 02:01:49 2014 +0200 2.2 +++ b/examples/imgthumbs/Makefile Fri Feb 07 07:50:02 2014 +0200 2.3 @@ -6,7 +6,7 @@ 2.4 bin = imgthumbs 2.5 2.6 CFLAGS = -pedantic -Wall -g -I../../src 2.7 -LDFLAGS = $(libgl) -limago 2.8 +LDFLAGS = $(libgl) -limago $(resman) -lpthread 2.9 2.10 ifeq ($(shell uname -s), Darwin) 2.11 libgl = -framework OpenGL -framework GLUT -lGLEW 2.12 @@ -14,9 +14,15 @@ 2.13 libgl = -lGL -lGLU -lglut -lGLEW 2.14 endif 2.15 2.16 -$(bin): $(obj) 2.17 +resman = ../../libresman.a 2.18 + 2.19 +$(bin): $(obj) resman 2.20 $(CC) -o $@ $(obj) $(LDFLAGS) 2.21 2.22 +.PHONY: resman 2.23 +resman: 2.24 + $(MAKE) -C ../.. 2.25 + 2.26 .PHONY: clean 2.27 clean: 2.28 rm -f $(obj) $(bin)
3.1 --- a/examples/imgthumbs/src/main.c Wed Feb 05 02:01:49 2014 +0200 3.2 +++ b/examples/imgthumbs/src/main.c Fri Feb 07 07:50:02 2014 +0200 3.3 @@ -1,6 +1,7 @@ 3.4 #include <stdio.h> 3.5 #include <stdlib.h> 3.6 #include <assert.h> 3.7 +#include <imago2.h> 3.8 #include "opengl.h" 3.9 #include "resman.h" 3.10 #include "thumbs.h" 3.11 @@ -17,7 +18,6 @@ 3.12 static struct thumbnail *find_thumb(int x, int y); 3.13 3.14 const char *path = "."; 3.15 -struct resman *texman; 3.16 int win_width, win_height; 3.17 float win_aspect; 3.18 float pan_x, pan_y; 3.19 @@ -40,6 +40,7 @@ 3.20 glutCreateWindow("imgthumbs"); 3.21 3.22 glutDisplayFunc(display); 3.23 + glutIdleFunc(glutPostRedisplay); 3.24 glutReshapeFunc(reshape); 3.25 glutKeyboardFunc(keyb); 3.26 glutMouseFunc(mouse); 3.27 @@ -68,6 +69,8 @@ 3.28 3.29 static void display(void) 3.30 { 3.31 + update_thumbs(); 3.32 + 3.33 glClear(GL_COLOR_BUFFER_BIT); 3.34 3.35 glMatrixMode(GL_MODELVIEW);
4.1 --- a/examples/imgthumbs/src/thumbs.c Wed Feb 05 02:01:49 2014 +0200 4.2 +++ b/examples/imgthumbs/src/thumbs.c Fri Feb 07 07:50:02 2014 +0200 4.3 @@ -2,25 +2,41 @@ 4.4 #include <stdlib.h> 4.5 #include <string.h> 4.6 #include <errno.h> 4.7 +#include <assert.h> 4.8 #include <dirent.h> 4.9 #include <imago2.h> 4.10 #include "opengl.h" 4.11 #include "thumbs.h" 4.12 +#include "resman.h" 4.13 4.14 #ifndef GL_COMPRESSED_RGB 4.15 #define GL_COMPRESSED_RGB 0x84ed 4.16 #endif 4.17 4.18 +struct resman *texman; 4.19 + 4.20 +static int load_res_texture(const char *fname, int id, void *cls); 4.21 +static int done_res_texture(int id, void *cls); 4.22 +static void free_res_texture(int id, void *cls); 4.23 + 4.24 + 4.25 struct thumbnail *create_thumbs(const char *dirpath) 4.26 { 4.27 DIR *dir; 4.28 struct dirent *dent; 4.29 struct thumbnail *list = 0; 4.30 4.31 - unsigned int intfmt = GL_COMPRESSED_RGB; 4.32 - if(!strstr(glGetString(GL_EXTENSIONS), "GL_ARB_texture_compression")) { 4.33 + /*unsigned int intfmt = GL_COMPRESSED_RGB; 4.34 + if(!strstr((char*)glGetString(GL_EXTENSIONS), "GL_ARB_texture_compression")) { 4.35 printf("warning, no texture compression available.\n"); 4.36 intfmt = GL_RGB; 4.37 + }*/ 4.38 + 4.39 + if(!texman) { 4.40 + texman = resman_create(); 4.41 + resman_set_load_func(texman, load_res_texture, 0); 4.42 + resman_set_done_func(texman, done_res_texture, 0); 4.43 + resman_set_destroy_func(texman, free_res_texture, 0); 4.44 } 4.45 4.46 if(!(dir = opendir(dirpath))) { 4.47 @@ -29,14 +45,15 @@ 4.48 } 4.49 4.50 while((dent = readdir(dir))) { 4.51 - int xsz, ysz; 4.52 - unsigned char *pixels; 4.53 + /*int xsz, ysz; 4.54 + unsigned char *pixels;*/ 4.55 struct thumbnail *node; 4.56 4.57 if(!(node = malloc(sizeof *node))) { 4.58 perror("failed to allocate thumbnail list node"); 4.59 continue; 4.60 } 4.61 + memset(node, 0, sizeof *node); 4.62 4.63 if(!(node->fname = malloc(strlen(dirpath) + strlen(dent->d_name) + 2))) { 4.64 free(node); 4.65 @@ -48,7 +65,11 @@ 4.66 } 4.67 strcat(node->fname, dent->d_name); 4.68 4.69 - if(!(pixels = img_load_pixels(node->fname, &xsz, &ysz, IMG_FMT_RGBA32))) { 4.70 + node->aspect = 1.0;/*(float)xsz / (float)ysz;*/ 4.71 + 4.72 + resman_lookup(texman, node->fname, 0); 4.73 + 4.74 + /*if(!(pixels = img_load_pixels(node->fname, &xsz, &ysz, IMG_FMT_RGBA32))) { 4.75 free(node->fname); 4.76 free(node); 4.77 continue; 4.78 @@ -62,8 +83,7 @@ 4.79 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 4.80 glTexImage2D(GL_TEXTURE_2D, 0, intfmt, xsz, ysz, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 4.81 img_free_pixels(pixels); 4.82 - 4.83 - node->aspect = (float)xsz / (float)ysz; 4.84 + */ 4.85 4.86 node->next = list; 4.87 list = node; 4.88 @@ -87,6 +107,11 @@ 4.89 } 4.90 4.91 4.92 +void update_thumbs(void) 4.93 +{ 4.94 + resman_poll(texman); 4.95 +} 4.96 + 4.97 void draw_thumbs(struct thumbnail *thumbs, float thumb_sz, float start_y) 4.98 { 4.99 int vp[4]; 4.100 @@ -106,6 +131,10 @@ 4.101 glMatrixMode(GL_MODELVIEW); 4.102 4.103 while(thumbs) { 4.104 + if(!thumbs->tex) { 4.105 + thumbs = thumbs->next; 4.106 + continue; 4.107 + } 4.108 4.109 glPushMatrix(); 4.110 glTranslatef(x, y, 0); 4.111 @@ -160,3 +189,67 @@ 4.112 glPopMatrix(); 4.113 glMatrixMode(GL_MODELVIEW); 4.114 } 4.115 + 4.116 +static int load_res_texture(const char *fname, int id, void *cls) 4.117 +{ 4.118 + struct resman *rman = cls; 4.119 + struct thumbnail *rdata = resman_get_res_data(rman, id); 4.120 + 4.121 + assert(rdata); 4.122 + if(!rdata->img) { 4.123 + if(!(rdata->img = img_create())) { 4.124 + return -1; 4.125 + } 4.126 + } 4.127 + 4.128 + if(!img_load(rdata->img, fname) == -1) { 4.129 + img_free(rdata->img); 4.130 + return -1; 4.131 + } 4.132 + rdata->aspect = (float)rdata->img->width / (float)rdata->img->height; 4.133 + 4.134 + /* set the resource's data to the loaded image, so that we can use 4.135 + * it in the done callback */ 4.136 + resman_set_res_data(rman, id, rdata); 4.137 + return 0; 4.138 +} 4.139 + 4.140 +static int done_res_texture(int id, void *cls) 4.141 +{ 4.142 + struct thumbnail *rdata; 4.143 + struct resman *rman = cls; 4.144 + 4.145 + rdata = resman_get_res_data(rman, id); 4.146 + 4.147 + if(resman_get_res_result(rman, id) != 0 || !rdata) { 4.148 + fprintf(stderr, "failed to load resource %d (%s)\n", id, resman_get_res_name(rman, id)); 4.149 + } else { 4.150 + printf("done loading resource %d (%s)\n", id, resman_get_res_name(rman, id)); 4.151 + } 4.152 + 4.153 + if(!rdata->tex) { 4.154 + glGenTextures(1, &rdata->tex); 4.155 + } 4.156 + glBindTexture(GL_TEXTURE_2D, rdata->tex); 4.157 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 4.158 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 4.159 + glTexImage2D(GL_TEXTURE_2D, 0, img_glintfmt(rdata->img), 4.160 + rdata->img->width, rdata->img->height, 0, img_glfmt(rdata->img), 4.161 + img_gltype(rdata->img), rdata->img->pixels); 4.162 + return 0; 4.163 +} 4.164 + 4.165 +static void free_res_texture(int id, void *cls) 4.166 +{ 4.167 + struct resman *rman = cls; 4.168 + struct thumbnail *rdata = resman_get_res_data(rman, id); 4.169 + 4.170 + if(rdata) { 4.171 + if(rdata->tex) { 4.172 + glDeleteTextures(1, &rdata->tex); 4.173 + } 4.174 + if(rdata->img) { 4.175 + img_free(rdata->img); 4.176 + } 4.177 + } 4.178 +}
5.1 --- a/examples/imgthumbs/src/thumbs.h Wed Feb 05 02:01:49 2014 +0200 5.2 +++ b/examples/imgthumbs/src/thumbs.h Fri Feb 07 07:50:02 2014 +0200 5.3 @@ -1,6 +1,7 @@ 5.4 #ifndef THUMBS_H_ 5.5 #define THUMBS_H_ 5.6 5.7 +struct img_pixmap; 5.8 5.9 struct thumbnail { 5.10 char *fname; 5.11 @@ -10,12 +11,15 @@ 5.12 float layout_pos[2]; 5.13 float layout_size[2]; 5.14 5.15 + struct img_pixmap *img; 5.16 + 5.17 struct thumbnail *next; 5.18 }; 5.19 5.20 struct thumbnail *create_thumbs(const char *dirpath); 5.21 void free_thumbs(struct thumbnail *thumbs); 5.22 5.23 +void update_thumbs(void); 5.24 void draw_thumbs(struct thumbnail *thumbs, float thumb_sz, float start_y); 5.25 5.26 #endif /* THUMBS_H_ */
6.1 --- a/src/resman.c Wed Feb 05 02:01:49 2014 +0200 6.2 +++ b/src/resman.c Fri Feb 07 07:50:02 2014 +0200 6.3 @@ -8,6 +8,7 @@ 6.4 #include "threadpool.h" 6.5 6.6 struct resource { 6.7 + int id; 6.8 char *name; 6.9 void *data; 6.10 int result; /* last callback-reported success/fail code */ 6.11 @@ -17,7 +18,7 @@ 6.12 }; 6.13 6.14 struct resman { 6.15 - struct resource *res; 6.16 + struct resource **res; 6.17 struct thread_pool *tpool; 6.18 6.19 resman_load_func load_func; 6.20 @@ -74,8 +75,9 @@ 6.21 6.22 for(i=0; i<dynarr_size(rman->res); i++) { 6.23 if(rman->destroy_func) { 6.24 - rman->destroy_func(rman->res[i].data, rman->destroy_func_cls); 6.25 + rman->destroy_func(i, rman->destroy_func_cls); 6.26 } 6.27 + free(rman->res[i]); 6.28 } 6.29 dynarr_free(rman->res); 6.30 6.31 @@ -128,8 +130,7 @@ 6.32 6.33 num_res = dynarr_size(rman->res); 6.34 for(i=0; i<num_res; i++) { 6.35 - struct resource *res = rman->res + i; 6.36 - int last_result; 6.37 + struct resource *res = rman->res[i]; 6.38 6.39 pthread_mutex_lock(&res->done_lock); 6.40 if(!res->done_pending) { 6.41 @@ -139,34 +140,39 @@ 6.42 6.43 /* so a done callback *is* pending... */ 6.44 res->done_pending = 0; 6.45 - last_result = res->result; 6.46 + rman->done_func(i, rman->done_func_cls); 6.47 pthread_mutex_unlock(&res->done_lock); 6.48 - 6.49 - rman->done_func(last_result, res->data, rman->done_func_cls); 6.50 } 6.51 return 0; 6.52 } 6.53 6.54 +const char *resman_get_res_name(struct resman *rman, int res_id) 6.55 +{ 6.56 + if(res_id >= 0 && res_id < dynarr_size(rman->res)) { 6.57 + return rman->res[res_id]->name; 6.58 + } 6.59 + return 0; 6.60 +} 6.61 6.62 void resman_set_res_data(struct resman *rman, int res_id, void *data) 6.63 { 6.64 if(res_id >= 0 && res_id < dynarr_size(rman->res)) { 6.65 - rman->res[res_id].data = data; 6.66 + rman->res[res_id]->data = data; 6.67 } 6.68 } 6.69 6.70 void *resman_get_res_data(struct resman *rman, int res_id) 6.71 { 6.72 if(res_id >= 0 && res_id < dynarr_size(rman->res)) { 6.73 - return rman->res[res_id].data; 6.74 + return rman->res[res_id]->data; 6.75 } 6.76 return 0; 6.77 } 6.78 6.79 -int resman_get_res_error(struct resman *rman, int res_id) 6.80 +int resman_get_res_result(struct resman *rman, int res_id) 6.81 { 6.82 if(res_id >= 0 && res_id < dynarr_size(rman->res)) { 6.83 - return rman->res[res_id].result; 6.84 + return rman->res[res_id]->result; 6.85 } 6.86 return -1; 6.87 } 6.88 @@ -176,7 +182,7 @@ 6.89 int i, sz = dynarr_size(rman->res); 6.90 6.91 for(i=0; i<sz; i++) { 6.92 - if(strcmp(rman->res[i].name, fname) == 0) { 6.93 + if(strcmp(rman->res[i]->name, fname) == 0) { 6.94 return i; 6.95 } 6.96 } 6.97 @@ -186,21 +192,25 @@ 6.98 static int add_resource(struct resman *rman, const char *fname, void *data) 6.99 { 6.100 int idx = dynarr_size(rman->res); 6.101 + struct resource *res; 6.102 + struct resource **tmparr; 6.103 6.104 - struct resource *tmp = dynarr_push(rman->res, 0); 6.105 - if(!tmp) { 6.106 + if(!(res = malloc(sizeof *res))) { 6.107 return -1; 6.108 } 6.109 - rman->res = tmp; 6.110 + res->id = idx; 6.111 + res->name = strdup(fname); 6.112 + assert(res->name); 6.113 + res->data = data; 6.114 6.115 - rman->res[idx].name = strdup(fname); 6.116 - assert(rman->res[idx].name); 6.117 - 6.118 - rman->res[idx].data = data; 6.119 + if(!(tmparr = dynarr_push(rman->res, &res))) { 6.120 + free(res); 6.121 + return -1; 6.122 + } 6.123 + rman->res = tmparr; 6.124 6.125 /* start a loading job ... */ 6.126 - tpool_add_work(rman->tpool, rman->res + idx); 6.127 - 6.128 + tpool_add_work(rman->tpool, rman->res[idx]); 6.129 return idx; 6.130 } 6.131 6.132 @@ -212,7 +222,7 @@ 6.133 struct resource *res = data; 6.134 struct resman *rman = cls; 6.135 6.136 - res->result = rman->load_func(res->name, res->data, rman->load_func_cls); 6.137 + res->result = rman->load_func(res->name, res->id, rman->load_func_cls); 6.138 pthread_mutex_lock(&res->done_lock); 6.139 res->done_pending = 1; 6.140 pthread_mutex_unlock(&res->done_lock);
7.1 --- a/src/resman.h Wed Feb 05 02:01:49 2014 +0200 7.2 +++ b/src/resman.h Fri Feb 07 07:50:02 2014 +0200 7.3 @@ -5,9 +5,9 @@ 7.4 * done callback: second-stage callback, called in the context of the 7.5 * user thread, after the load callback returns 7.6 */ 7.7 -typedef int (*resman_load_func)(const char *fname, void *data, void *closure); 7.8 -typedef int (*resman_done_func)(int result, void *data, void *closure); 7.9 -typedef void (*resman_destroy_func)(void *data, void *closure); 7.10 +typedef int (*resman_load_func)(const char *fname, int id, void *closure); 7.11 +typedef int (*resman_done_func)(int id, void *closure); 7.12 +typedef void (*resman_destroy_func)(int id, void *closure); 7.13 7.14 struct resman; 7.15 7.16 @@ -30,10 +30,12 @@ 7.17 7.18 int resman_poll(struct resman *rman); 7.19 7.20 +const char *resman_get_res_name(struct resman *rman, int res_id); 7.21 + 7.22 void resman_set_res_data(struct resman *rman, int res_id, void *data); 7.23 void *resman_get_res_data(struct resman *rman, int res_id); 7.24 7.25 -int resman_get_res_error(struct resman *rman, int res_id); 7.26 +int resman_get_res_result(struct resman *rman, int res_id); 7.27 7.28 #ifdef __cplusplus 7.29 }
8.1 --- a/src/threadpool.c Wed Feb 05 02:01:49 2014 +0200 8.2 +++ b/src/threadpool.c Fri Feb 07 07:50:02 2014 +0200 8.3 @@ -37,6 +37,11 @@ 8.4 8.5 memset(tpool, 0, sizeof *tpool); 8.6 8.7 + 8.8 + pthread_mutex_init(&tpool->work_lock, 0); 8.9 + pthread_cond_init(&tpool->work_cond, 0); 8.10 + 8.11 + 8.12 if(num_threads <= 0) { 8.13 num_threads = get_processor_count(); 8.14 } 8.15 @@ -44,6 +49,11 @@ 8.16 8.17 printf("initializing thread pool with %d worker threads\n", num_threads); 8.18 8.19 + if(!(tpool->workers = malloc(num_threads * sizeof *tpool->workers))) { 8.20 + fprintf(stderr, "failed to create array of %d threads\n", num_threads); 8.21 + return -1; 8.22 + } 8.23 + 8.24 for(i=0; i<num_threads; i++) { 8.25 if(pthread_create(tpool->workers + i, 0, thread_func, tpool) == -1) { 8.26 fprintf(stderr, "%s: failed to create thread %d\n", __FUNCTION__, i); 8.27 @@ -51,9 +61,6 @@ 8.28 return -1; 8.29 } 8.30 } 8.31 - 8.32 - pthread_mutex_init(&tpool->work_lock, 0); 8.33 - pthread_cond_init(&tpool->work_cond, 0); 8.34 return 0; 8.35 } 8.36