libresman

annotate examples/imgthumbs/src/thumbs.c @ 18:711698580eb0

fixed visual studio build directories fixed debug id problem with the thread pool
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 12 Feb 2014 06:53:30 +0200
parents 43a9fe4a80ee
children c6073bf9fd38
rev   line source
nuclear@1 1 #include <stdio.h>
nuclear@1 2 #include <stdlib.h>
nuclear@1 3 #include <string.h>
nuclear@1 4 #include <errno.h>
nuclear@11 5 #include <assert.h>
nuclear@1 6 #include <dirent.h>
nuclear@1 7 #include <imago2.h>
nuclear@1 8 #include "opengl.h"
nuclear@1 9 #include "thumbs.h"
nuclear@11 10 #include "resman.h"
nuclear@1 11
nuclear@18 12 #undef DBG_SYNC
nuclear@16 13
nuclear@6 14 #ifndef GL_COMPRESSED_RGB
nuclear@6 15 #define GL_COMPRESSED_RGB 0x84ed
nuclear@6 16 #endif
nuclear@6 17
nuclear@11 18 struct resman *texman;
nuclear@14 19 struct thumbnail *dbg;
nuclear@11 20
nuclear@11 21 static int load_res_texture(const char *fname, int id, void *cls);
nuclear@11 22 static int done_res_texture(int id, void *cls);
nuclear@11 23 static void free_res_texture(int id, void *cls);
nuclear@11 24
nuclear@11 25
nuclear@1 26 struct thumbnail *create_thumbs(const char *dirpath)
nuclear@1 27 {
nuclear@1 28 DIR *dir;
nuclear@1 29 struct dirent *dent;
nuclear@13 30 /* allocate dummy head node */
nuclear@13 31 struct thumbnail *list = calloc(1, sizeof *list);
nuclear@14 32 dbg = list;
nuclear@1 33
nuclear@11 34 if(!texman) {
nuclear@11 35 texman = resman_create();
nuclear@11 36 resman_set_load_func(texman, load_res_texture, 0);
nuclear@11 37 resman_set_done_func(texman, done_res_texture, 0);
nuclear@11 38 resman_set_destroy_func(texman, free_res_texture, 0);
nuclear@2 39 }
nuclear@2 40
nuclear@1 41 if(!(dir = opendir(dirpath))) {
nuclear@1 42 fprintf(stderr, "failed to open directory: %s: %s\n", dirpath, strerror(errno));
nuclear@1 43 return 0;
nuclear@1 44 }
nuclear@1 45
nuclear@1 46 while((dent = readdir(dir))) {
nuclear@16 47 #ifdef DBG_SYNC
nuclear@18 48 struct img_pixmap img;
nuclear@16 49 #endif
nuclear@1 50 struct thumbnail *node;
nuclear@1 51
nuclear@1 52 if(!(node = malloc(sizeof *node))) {
nuclear@1 53 perror("failed to allocate thumbnail list node");
nuclear@1 54 continue;
nuclear@1 55 }
nuclear@11 56 memset(node, 0, sizeof *node);
nuclear@1 57
nuclear@1 58 if(!(node->fname = malloc(strlen(dirpath) + strlen(dent->d_name) + 2))) {
nuclear@1 59 free(node);
nuclear@1 60 continue;
nuclear@1 61 }
nuclear@1 62 strcpy(node->fname, dirpath);
nuclear@1 63 if(dirpath[strlen(dirpath) - 1] != '/') {
nuclear@1 64 strcat(node->fname, "/");
nuclear@1 65 }
nuclear@1 66 strcat(node->fname, dent->d_name);
nuclear@1 67
nuclear@16 68 node->aspect = 1.0;
nuclear@11 69
nuclear@16 70 #ifndef DBG_SYNC
nuclear@12 71 resman_lookup(texman, node->fname, node);
nuclear@16 72 #else
nuclear@18 73 img_init(&img);
nuclear@18 74 if(img_load(&img, node->fname) == -1) {
nuclear@18 75 img_destroy(&img);
nuclear@1 76 free(node->fname);
nuclear@1 77 free(node);
nuclear@1 78 continue;
nuclear@1 79 }
nuclear@1 80
nuclear@1 81 printf("loaded image: %s\n", node->fname);
nuclear@1 82
nuclear@18 83 node->aspect = (float)img.width / (float)img.height;
nuclear@18 84
nuclear@1 85 glGenTextures(1, &node->tex);
nuclear@1 86 glBindTexture(GL_TEXTURE_2D, node->tex);
nuclear@1 87 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
nuclear@1 88 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
nuclear@18 89 glTexImage2D(GL_TEXTURE_2D, 0, img_glintfmt(&img), img.width, img.height, 0, img_glfmt(&img), img_gltype(&img), img.pixels);
nuclear@18 90 img_destroy(&img);
nuclear@16 91 #endif
nuclear@1 92
nuclear@13 93 node->next = list->next;
nuclear@13 94 node->prev = list;
nuclear@14 95 list->next = node;
nuclear@1 96 }
nuclear@1 97 closedir(dir);
nuclear@1 98
nuclear@1 99 return list;
nuclear@1 100 }
nuclear@1 101
nuclear@1 102 void free_thumbs(struct thumbnail *thumbs)
nuclear@1 103 {
nuclear@1 104 if(!thumbs) return;
nuclear@1 105
nuclear@1 106 while(thumbs) {
nuclear@1 107 struct thumbnail *tmp = thumbs;
nuclear@1 108 thumbs = thumbs->next;
nuclear@1 109
nuclear@1 110 free(tmp->fname);
nuclear@1 111 free(tmp);
nuclear@1 112 }
nuclear@1 113 }
nuclear@1 114
nuclear@1 115
nuclear@11 116 void update_thumbs(void)
nuclear@11 117 {
nuclear@11 118 resman_poll(texman);
nuclear@11 119 }
nuclear@11 120
nuclear@1 121 void draw_thumbs(struct thumbnail *thumbs, float thumb_sz, float start_y)
nuclear@1 122 {
nuclear@1 123 int vp[4];
nuclear@1 124 float gap = thumb_sz / 4.0;
nuclear@1 125 float x = gap;
nuclear@1 126 float y = gap + start_y;
nuclear@1 127 float view_aspect;
nuclear@1 128
nuclear@1 129 glGetIntegerv(GL_VIEWPORT, vp);
nuclear@14 130 view_aspect = (float)(vp[2] - vp[0]) / (float)(vp[3] - vp[1]);
nuclear@1 131
nuclear@1 132 glMatrixMode(GL_PROJECTION);
nuclear@1 133 glPushMatrix();
nuclear@1 134 glLoadIdentity();
nuclear@1 135 glOrtho(0, 1, 1.0 / view_aspect, 0, -1, 1);
nuclear@1 136
nuclear@1 137 glMatrixMode(GL_MODELVIEW);
nuclear@1 138
nuclear@13 139 thumbs = thumbs->next; /* skip dummy node */
nuclear@1 140 while(thumbs) {
nuclear@14 141 printf("drawing thumb: %s\n", thumbs->fname);
nuclear@1 142 glPushMatrix();
nuclear@1 143 glTranslatef(x, y, 0);
nuclear@1 144
nuclear@1 145 glScalef(thumb_sz, thumb_sz, 1);
nuclear@1 146
nuclear@1 147 glBegin(GL_QUADS);
nuclear@1 148 glColor3f(0.25, 0.25, 0.25);
nuclear@1 149 glTexCoord2f(0, 0); glVertex2f(0, 0);
nuclear@1 150 glTexCoord2f(1, 0); glVertex2f(1, 0);
nuclear@1 151 glTexCoord2f(1, 1); glVertex2f(1, 1);
nuclear@1 152 glTexCoord2f(0, 1); glVertex2f(0, 1);
nuclear@1 153 glEnd();
nuclear@1 154
nuclear@12 155 if(thumbs->tex) {
nuclear@12 156 if(thumbs->aspect >= 1.0) {
nuclear@12 157 glTranslatef(0, 0.5 - 0.5 / thumbs->aspect, 0);
nuclear@12 158 glScalef(1, 1.0 / thumbs->aspect, 1);
nuclear@12 159 } else {
nuclear@12 160 glTranslatef(0.5 - thumbs->aspect / 2.0, 0, 0);
nuclear@12 161 glScalef(thumbs->aspect, 1, 1);
nuclear@12 162 }
nuclear@12 163
nuclear@12 164 if(glIsTexture(thumbs->tex)) {
nuclear@12 165 glEnable(GL_TEXTURE_2D);
nuclear@12 166 glBindTexture(GL_TEXTURE_2D, thumbs->tex);
nuclear@12 167
nuclear@12 168 glBegin(GL_QUADS);
nuclear@12 169 glColor3f(1, 1, 1);
nuclear@12 170 glTexCoord2f(0, 0); glVertex2f(0, 0);
nuclear@12 171 glTexCoord2f(1, 0); glVertex2f(1, 0);
nuclear@12 172 glTexCoord2f(1, 1); glVertex2f(1, 1);
nuclear@12 173 glTexCoord2f(0, 1); glVertex2f(0, 1);
nuclear@12 174 glEnd();
nuclear@12 175 } else {
nuclear@12 176 fprintf(stderr, "invalid texture: %u\n", thumbs->tex);
nuclear@12 177 }
nuclear@12 178
nuclear@12 179 glPopMatrix();
nuclear@12 180 glDisable(GL_TEXTURE_2D);
nuclear@1 181 }
nuclear@1 182
nuclear@1 183 thumbs->layout_pos[0] = x;
nuclear@1 184 thumbs->layout_pos[1] = y;
nuclear@1 185 thumbs->layout_size[0] = thumb_sz;
nuclear@1 186 thumbs->layout_size[1] = thumb_sz;
nuclear@1 187
nuclear@1 188 x += thumb_sz + gap;
nuclear@1 189 if(x >= 1.0 - thumb_sz) {
nuclear@1 190 x = gap;
nuclear@1 191 y += thumb_sz + gap;
nuclear@1 192 }
nuclear@1 193
nuclear@1 194 thumbs = thumbs->next;
nuclear@1 195 }
nuclear@1 196
nuclear@1 197 glMatrixMode(GL_PROJECTION);
nuclear@1 198 glPopMatrix();
nuclear@1 199 glMatrixMode(GL_MODELVIEW);
nuclear@1 200 }
nuclear@11 201
nuclear@11 202 static int load_res_texture(const char *fname, int id, void *cls)
nuclear@11 203 {
nuclear@12 204 struct thumbnail *rdata = resman_get_res_data(texman, id);
nuclear@11 205
nuclear@11 206 assert(rdata);
nuclear@11 207 if(!rdata->img) {
nuclear@11 208 if(!(rdata->img = img_create())) {
nuclear@11 209 return -1;
nuclear@11 210 }
nuclear@11 211 }
nuclear@11 212
nuclear@12 213 if(img_load(rdata->img, fname) == -1) {
nuclear@11 214 img_free(rdata->img);
nuclear@13 215 rdata->img = 0;
nuclear@11 216 return -1;
nuclear@11 217 }
nuclear@11 218 rdata->aspect = (float)rdata->img->width / (float)rdata->img->height;
nuclear@11 219
nuclear@11 220 /* set the resource's data to the loaded image, so that we can use
nuclear@11 221 * it in the done callback */
nuclear@12 222 resman_set_res_data(texman, id, rdata);
nuclear@11 223 return 0;
nuclear@11 224 }
nuclear@11 225
nuclear@11 226 static int done_res_texture(int id, void *cls)
nuclear@11 227 {
nuclear@13 228 struct thumbnail *rdata = resman_get_res_data(texman, id);
nuclear@13 229 int load_result = resman_get_res_result(texman, id);
nuclear@11 230
nuclear@13 231 if(load_result == -1) {
nuclear@13 232 /* returning -1 will remove this resource, the free_res_texture
nuclear@13 233 * destroy handler will be called, which will remove the node
nuclear@13 234 * from the list
nuclear@13 235 */
nuclear@13 236 return -1;
nuclear@13 237 }
nuclear@11 238
nuclear@12 239 if(resman_get_res_result(texman, id) != 0 || !rdata) {
nuclear@12 240 fprintf(stderr, "failed to load resource %d (%s)\n", id, resman_get_res_name(texman, id));
nuclear@11 241 } else {
nuclear@12 242 printf("done loading resource %d (%s)\n", id, resman_get_res_name(texman, id));
nuclear@11 243 }
nuclear@11 244
nuclear@11 245 if(!rdata->tex) {
nuclear@11 246 glGenTextures(1, &rdata->tex);
nuclear@11 247 }
nuclear@11 248 glBindTexture(GL_TEXTURE_2D, rdata->tex);
nuclear@11 249 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
nuclear@11 250 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
nuclear@11 251 glTexImage2D(GL_TEXTURE_2D, 0, img_glintfmt(rdata->img),
nuclear@11 252 rdata->img->width, rdata->img->height, 0, img_glfmt(rdata->img),
nuclear@11 253 img_gltype(rdata->img), rdata->img->pixels);
nuclear@11 254 return 0;
nuclear@11 255 }
nuclear@11 256
nuclear@11 257 static void free_res_texture(int id, void *cls)
nuclear@11 258 {
nuclear@13 259 struct thumbnail *thumb = resman_get_res_data(texman, id);
nuclear@11 260
nuclear@14 261 printf("deleting thumb %d: %s\n", id, thumb->fname);
nuclear@14 262
nuclear@13 263 if(thumb) {
nuclear@13 264 if(thumb->tex) {
nuclear@13 265 glDeleteTextures(1, &thumb->tex);
nuclear@11 266 }
nuclear@13 267 if(thumb->img) {
nuclear@13 268 img_free(thumb->img);
nuclear@11 269 }
nuclear@11 270 }
nuclear@13 271
nuclear@13 272 /* remove from the list */
nuclear@13 273 if(thumb->prev) {
nuclear@13 274 thumb->prev->next = thumb->next;
nuclear@13 275 }
nuclear@13 276 if(thumb->next) {
nuclear@13 277 thumb->next->prev = thumb->prev;
nuclear@13 278 }
nuclear@13 279 free(thumb);
nuclear@11 280 }