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