# HG changeset patch # User John Tsiombikas # Date 1391752202 -7200 # Node ID bebc065a941fdc808ed732bc7e56c547c6282bf2 # Parent 4d18498a007899f4a127b147b4f53a03fc79e9d4 doesn't work yet diff -r 4d18498a0078 -r bebc065a941f examples/imgthumbs/.clang_complete --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/imgthumbs/.clang_complete Fri Feb 07 07:50:02 2014 +0200 @@ -0,0 +1,1 @@ +-I../../src diff -r 4d18498a0078 -r bebc065a941f examples/imgthumbs/Makefile --- a/examples/imgthumbs/Makefile Wed Feb 05 02:01:49 2014 +0200 +++ b/examples/imgthumbs/Makefile Fri Feb 07 07:50:02 2014 +0200 @@ -6,7 +6,7 @@ bin = imgthumbs CFLAGS = -pedantic -Wall -g -I../../src -LDFLAGS = $(libgl) -limago +LDFLAGS = $(libgl) -limago $(resman) -lpthread ifeq ($(shell uname -s), Darwin) libgl = -framework OpenGL -framework GLUT -lGLEW @@ -14,9 +14,15 @@ libgl = -lGL -lGLU -lglut -lGLEW endif -$(bin): $(obj) +resman = ../../libresman.a + +$(bin): $(obj) resman $(CC) -o $@ $(obj) $(LDFLAGS) +.PHONY: resman +resman: + $(MAKE) -C ../.. + .PHONY: clean clean: rm -f $(obj) $(bin) diff -r 4d18498a0078 -r bebc065a941f examples/imgthumbs/src/main.c --- a/examples/imgthumbs/src/main.c Wed Feb 05 02:01:49 2014 +0200 +++ b/examples/imgthumbs/src/main.c Fri Feb 07 07:50:02 2014 +0200 @@ -1,6 +1,7 @@ #include #include #include +#include #include "opengl.h" #include "resman.h" #include "thumbs.h" @@ -17,7 +18,6 @@ static struct thumbnail *find_thumb(int x, int y); const char *path = "."; -struct resman *texman; int win_width, win_height; float win_aspect; float pan_x, pan_y; @@ -40,6 +40,7 @@ glutCreateWindow("imgthumbs"); glutDisplayFunc(display); + glutIdleFunc(glutPostRedisplay); glutReshapeFunc(reshape); glutKeyboardFunc(keyb); glutMouseFunc(mouse); @@ -68,6 +69,8 @@ static void display(void) { + update_thumbs(); + glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); diff -r 4d18498a0078 -r bebc065a941f examples/imgthumbs/src/thumbs.c --- a/examples/imgthumbs/src/thumbs.c Wed Feb 05 02:01:49 2014 +0200 +++ b/examples/imgthumbs/src/thumbs.c Fri Feb 07 07:50:02 2014 +0200 @@ -2,25 +2,41 @@ #include #include #include +#include #include #include #include "opengl.h" #include "thumbs.h" +#include "resman.h" #ifndef GL_COMPRESSED_RGB #define GL_COMPRESSED_RGB 0x84ed #endif +struct resman *texman; + +static int load_res_texture(const char *fname, int id, void *cls); +static int done_res_texture(int id, void *cls); +static void free_res_texture(int id, void *cls); + + struct thumbnail *create_thumbs(const char *dirpath) { DIR *dir; struct dirent *dent; struct thumbnail *list = 0; - unsigned int intfmt = GL_COMPRESSED_RGB; - if(!strstr(glGetString(GL_EXTENSIONS), "GL_ARB_texture_compression")) { + /*unsigned int intfmt = GL_COMPRESSED_RGB; + if(!strstr((char*)glGetString(GL_EXTENSIONS), "GL_ARB_texture_compression")) { printf("warning, no texture compression available.\n"); intfmt = GL_RGB; + }*/ + + if(!texman) { + texman = resman_create(); + resman_set_load_func(texman, load_res_texture, 0); + resman_set_done_func(texman, done_res_texture, 0); + resman_set_destroy_func(texman, free_res_texture, 0); } if(!(dir = opendir(dirpath))) { @@ -29,14 +45,15 @@ } while((dent = readdir(dir))) { - int xsz, ysz; - unsigned char *pixels; + /*int xsz, ysz; + unsigned char *pixels;*/ struct thumbnail *node; if(!(node = malloc(sizeof *node))) { perror("failed to allocate thumbnail list node"); continue; } + memset(node, 0, sizeof *node); if(!(node->fname = malloc(strlen(dirpath) + strlen(dent->d_name) + 2))) { free(node); @@ -48,7 +65,11 @@ } strcat(node->fname, dent->d_name); - if(!(pixels = img_load_pixels(node->fname, &xsz, &ysz, IMG_FMT_RGBA32))) { + node->aspect = 1.0;/*(float)xsz / (float)ysz;*/ + + resman_lookup(texman, node->fname, 0); + + /*if(!(pixels = img_load_pixels(node->fname, &xsz, &ysz, IMG_FMT_RGBA32))) { free(node->fname); free(node); continue; @@ -62,8 +83,7 @@ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, intfmt, xsz, ysz, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); img_free_pixels(pixels); - - node->aspect = (float)xsz / (float)ysz; + */ node->next = list; list = node; @@ -87,6 +107,11 @@ } +void update_thumbs(void) +{ + resman_poll(texman); +} + void draw_thumbs(struct thumbnail *thumbs, float thumb_sz, float start_y) { int vp[4]; @@ -106,6 +131,10 @@ glMatrixMode(GL_MODELVIEW); while(thumbs) { + if(!thumbs->tex) { + thumbs = thumbs->next; + continue; + } glPushMatrix(); glTranslatef(x, y, 0); @@ -160,3 +189,67 @@ glPopMatrix(); glMatrixMode(GL_MODELVIEW); } + +static int load_res_texture(const char *fname, int id, void *cls) +{ + struct resman *rman = cls; + struct thumbnail *rdata = resman_get_res_data(rman, id); + + assert(rdata); + if(!rdata->img) { + if(!(rdata->img = img_create())) { + return -1; + } + } + + if(!img_load(rdata->img, fname) == -1) { + img_free(rdata->img); + return -1; + } + rdata->aspect = (float)rdata->img->width / (float)rdata->img->height; + + /* set the resource's data to the loaded image, so that we can use + * it in the done callback */ + resman_set_res_data(rman, id, rdata); + return 0; +} + +static int done_res_texture(int id, void *cls) +{ + struct thumbnail *rdata; + struct resman *rman = cls; + + rdata = resman_get_res_data(rman, id); + + if(resman_get_res_result(rman, id) != 0 || !rdata) { + fprintf(stderr, "failed to load resource %d (%s)\n", id, resman_get_res_name(rman, id)); + } else { + printf("done loading resource %d (%s)\n", id, resman_get_res_name(rman, id)); + } + + if(!rdata->tex) { + glGenTextures(1, &rdata->tex); + } + glBindTexture(GL_TEXTURE_2D, rdata->tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, img_glintfmt(rdata->img), + rdata->img->width, rdata->img->height, 0, img_glfmt(rdata->img), + img_gltype(rdata->img), rdata->img->pixels); + return 0; +} + +static void free_res_texture(int id, void *cls) +{ + struct resman *rman = cls; + struct thumbnail *rdata = resman_get_res_data(rman, id); + + if(rdata) { + if(rdata->tex) { + glDeleteTextures(1, &rdata->tex); + } + if(rdata->img) { + img_free(rdata->img); + } + } +} diff -r 4d18498a0078 -r bebc065a941f examples/imgthumbs/src/thumbs.h --- a/examples/imgthumbs/src/thumbs.h Wed Feb 05 02:01:49 2014 +0200 +++ b/examples/imgthumbs/src/thumbs.h Fri Feb 07 07:50:02 2014 +0200 @@ -1,6 +1,7 @@ #ifndef THUMBS_H_ #define THUMBS_H_ +struct img_pixmap; struct thumbnail { char *fname; @@ -10,12 +11,15 @@ float layout_pos[2]; float layout_size[2]; + struct img_pixmap *img; + struct thumbnail *next; }; struct thumbnail *create_thumbs(const char *dirpath); void free_thumbs(struct thumbnail *thumbs); +void update_thumbs(void); void draw_thumbs(struct thumbnail *thumbs, float thumb_sz, float start_y); #endif /* THUMBS_H_ */ diff -r 4d18498a0078 -r bebc065a941f src/resman.c --- a/src/resman.c Wed Feb 05 02:01:49 2014 +0200 +++ b/src/resman.c Fri Feb 07 07:50:02 2014 +0200 @@ -8,6 +8,7 @@ #include "threadpool.h" struct resource { + int id; char *name; void *data; int result; /* last callback-reported success/fail code */ @@ -17,7 +18,7 @@ }; struct resman { - struct resource *res; + struct resource **res; struct thread_pool *tpool; resman_load_func load_func; @@ -74,8 +75,9 @@ for(i=0; ires); i++) { if(rman->destroy_func) { - rman->destroy_func(rman->res[i].data, rman->destroy_func_cls); + rman->destroy_func(i, rman->destroy_func_cls); } + free(rman->res[i]); } dynarr_free(rman->res); @@ -128,8 +130,7 @@ num_res = dynarr_size(rman->res); for(i=0; ires + i; - int last_result; + struct resource *res = rman->res[i]; pthread_mutex_lock(&res->done_lock); if(!res->done_pending) { @@ -139,34 +140,39 @@ /* so a done callback *is* pending... */ res->done_pending = 0; - last_result = res->result; + rman->done_func(i, rman->done_func_cls); pthread_mutex_unlock(&res->done_lock); - - rman->done_func(last_result, res->data, rman->done_func_cls); } return 0; } +const char *resman_get_res_name(struct resman *rman, int res_id) +{ + if(res_id >= 0 && res_id < dynarr_size(rman->res)) { + return rman->res[res_id]->name; + } + return 0; +} void resman_set_res_data(struct resman *rman, int res_id, void *data) { if(res_id >= 0 && res_id < dynarr_size(rman->res)) { - rman->res[res_id].data = data; + rman->res[res_id]->data = data; } } void *resman_get_res_data(struct resman *rman, int res_id) { if(res_id >= 0 && res_id < dynarr_size(rman->res)) { - return rman->res[res_id].data; + return rman->res[res_id]->data; } return 0; } -int resman_get_res_error(struct resman *rman, int res_id) +int resman_get_res_result(struct resman *rman, int res_id) { if(res_id >= 0 && res_id < dynarr_size(rman->res)) { - return rman->res[res_id].result; + return rman->res[res_id]->result; } return -1; } @@ -176,7 +182,7 @@ int i, sz = dynarr_size(rman->res); for(i=0; ires[i].name, fname) == 0) { + if(strcmp(rman->res[i]->name, fname) == 0) { return i; } } @@ -186,21 +192,25 @@ static int add_resource(struct resman *rman, const char *fname, void *data) { int idx = dynarr_size(rman->res); + struct resource *res; + struct resource **tmparr; - struct resource *tmp = dynarr_push(rman->res, 0); - if(!tmp) { + if(!(res = malloc(sizeof *res))) { return -1; } - rman->res = tmp; + res->id = idx; + res->name = strdup(fname); + assert(res->name); + res->data = data; - rman->res[idx].name = strdup(fname); - assert(rman->res[idx].name); - - rman->res[idx].data = data; + if(!(tmparr = dynarr_push(rman->res, &res))) { + free(res); + return -1; + } + rman->res = tmparr; /* start a loading job ... */ - tpool_add_work(rman->tpool, rman->res + idx); - + tpool_add_work(rman->tpool, rman->res[idx]); return idx; } @@ -212,7 +222,7 @@ struct resource *res = data; struct resman *rman = cls; - res->result = rman->load_func(res->name, res->data, rman->load_func_cls); + res->result = rman->load_func(res->name, res->id, rman->load_func_cls); pthread_mutex_lock(&res->done_lock); res->done_pending = 1; pthread_mutex_unlock(&res->done_lock); diff -r 4d18498a0078 -r bebc065a941f src/resman.h --- a/src/resman.h Wed Feb 05 02:01:49 2014 +0200 +++ b/src/resman.h Fri Feb 07 07:50:02 2014 +0200 @@ -5,9 +5,9 @@ * done callback: second-stage callback, called in the context of the * user thread, after the load callback returns */ -typedef int (*resman_load_func)(const char *fname, void *data, void *closure); -typedef int (*resman_done_func)(int result, void *data, void *closure); -typedef void (*resman_destroy_func)(void *data, void *closure); +typedef int (*resman_load_func)(const char *fname, int id, void *closure); +typedef int (*resman_done_func)(int id, void *closure); +typedef void (*resman_destroy_func)(int id, void *closure); struct resman; @@ -30,10 +30,12 @@ int resman_poll(struct resman *rman); +const char *resman_get_res_name(struct resman *rman, int res_id); + void resman_set_res_data(struct resman *rman, int res_id, void *data); void *resman_get_res_data(struct resman *rman, int res_id); -int resman_get_res_error(struct resman *rman, int res_id); +int resman_get_res_result(struct resman *rman, int res_id); #ifdef __cplusplus } diff -r 4d18498a0078 -r bebc065a941f src/threadpool.c --- a/src/threadpool.c Wed Feb 05 02:01:49 2014 +0200 +++ b/src/threadpool.c Fri Feb 07 07:50:02 2014 +0200 @@ -37,6 +37,11 @@ memset(tpool, 0, sizeof *tpool); + + pthread_mutex_init(&tpool->work_lock, 0); + pthread_cond_init(&tpool->work_cond, 0); + + if(num_threads <= 0) { num_threads = get_processor_count(); } @@ -44,6 +49,11 @@ printf("initializing thread pool with %d worker threads\n", num_threads); + if(!(tpool->workers = malloc(num_threads * sizeof *tpool->workers))) { + fprintf(stderr, "failed to create array of %d threads\n", num_threads); + return -1; + } + for(i=0; iworkers + i, 0, thread_func, tpool) == -1) { fprintf(stderr, "%s: failed to create thread %d\n", __FUNCTION__, i); @@ -51,9 +61,6 @@ return -1; } } - - pthread_mutex_init(&tpool->work_lock, 0); - pthread_cond_init(&tpool->work_cond, 0); return 0; }