nuclear@17: #include nuclear@17: #include nuclear@17: #include nuclear@17: #include nuclear@17: #include nuclear@17: #include "opengl.h" nuclear@17: #include "texture.h" nuclear@17: #include "imago2.h" nuclear@17: #include "rbtree.h" nuclear@17: #include "assman.h" nuclear@17: nuclear@17: static size_t ioread(void *buf, size_t bytes, void *uptr); nuclear@17: static long ioseek(long offs, int whence, void *uptr); nuclear@17: static unsigned int next_pow2(unsigned int x); nuclear@17: nuclear@17: static struct rbtree *texdb; nuclear@17: nuclear@17: int load_texture(struct texture *tex, const char *fname) nuclear@17: { nuclear@17: struct img_pixmap img; nuclear@17: struct img_io io; nuclear@17: ass_file *fp; nuclear@17: nuclear@17: printf("loading texture: %s\n", fname); nuclear@17: nuclear@17: if(!(fp = ass_fopen(fname, "rb"))) { nuclear@17: fprintf(stderr, "failed to open texture file: %s: %s\n", fname, strerror(errno)); nuclear@17: return -1; nuclear@17: } nuclear@17: io.uptr = fp; nuclear@17: io.read = ioread; nuclear@17: io.write = 0; nuclear@17: io.seek = ioseek; nuclear@17: nuclear@17: img_init(&img); nuclear@17: if(img_read(&img, &io) == -1) { nuclear@17: fprintf(stderr, "failed to load texture file: %s\n", fname); nuclear@17: ass_fclose(fp); nuclear@17: return -1; nuclear@17: } nuclear@17: img_convert(&img, IMG_FMT_RGBA32); nuclear@17: nuclear@17: tex->img_width = img.width; nuclear@17: tex->img_height = img.height; nuclear@17: tex->width = next_pow2(img.width); nuclear@17: tex->height = next_pow2(img.height); nuclear@17: nuclear@17: printf(" %dx%d (tex: %dx%d)\n", tex->img_width, tex->img_height, tex->width, tex->height); nuclear@17: nuclear@17: glGenTextures(1, &tex->texid); nuclear@17: glBindTexture(GL_TEXTURE_2D, tex->texid); nuclear@17: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); nuclear@17: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); nuclear@17: nuclear@17: #ifdef __GLEW_H__ nuclear@17: if(GLEW_SGIS_generate_mipmap) { nuclear@17: glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); nuclear@17: #endif nuclear@17: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex->width, tex->height, 0, nuclear@17: GL_RGBA, GL_UNSIGNED_BYTE, img.pixels); nuclear@17: #ifdef __GLEW_H__ nuclear@17: } else { nuclear@17: gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, tex->width, tex->height, nuclear@17: GL_RGBA, GL_UNSIGNED_BYTE, img.pixels); nuclear@17: } nuclear@17: #endif nuclear@17: nuclear@17: #ifdef GL_ES_VERSION_2_0 nuclear@17: glGenerateMipmap(GL_TEXTURE_2D); nuclear@17: #endif nuclear@17: nuclear@17: return 0; nuclear@17: } nuclear@17: nuclear@17: struct texture *get_texture(const char *fname) nuclear@17: { nuclear@17: struct texture *tex; nuclear@17: struct rbnode *node; nuclear@17: nuclear@17: if(!(texdb = rb_create(RB_KEY_STRING))) { nuclear@17: static int err_printed; nuclear@17: if(!err_printed) { nuclear@17: fprintf(stderr, "failed to create texture database\n"); nuclear@17: err_printed = 1; nuclear@17: } nuclear@17: return 0; nuclear@17: } nuclear@17: nuclear@17: if((node = rb_find(texdb, (void*)fname))) { nuclear@17: return rb_node_data(node); nuclear@17: } nuclear@17: nuclear@17: if(!(tex = malloc(sizeof *tex))) { nuclear@17: fprintf(stderr, "failed to load texture \"%s\": %s\n", fname, strerror(errno)); nuclear@17: return 0; nuclear@17: } nuclear@17: if(load_texture(tex, fname) == -1) { nuclear@17: free(tex); nuclear@17: return 0; nuclear@17: } nuclear@17: nuclear@17: if(rb_insert(texdb, (void*)fname, tex) == -1) { nuclear@17: fprintf(stderr, "failed to insert texture into the texture database\n"); nuclear@17: } nuclear@17: return tex; nuclear@17: } nuclear@17: nuclear@17: nuclear@17: #define DBG_TEX_SZ 64 nuclear@17: int gen_debug_texture(struct texture *tex) nuclear@17: { nuclear@17: static unsigned char *pixels; nuclear@17: nuclear@17: if(!pixels) { nuclear@17: int i, j; nuclear@17: unsigned char *pptr; nuclear@17: pptr = pixels = malloc(DBG_TEX_SZ * DBG_TEX_SZ * 4); nuclear@17: assert(pixels); nuclear@17: nuclear@17: for(i=0; i> 3) & 1) == ((i >> 3) & 1); nuclear@17: *pptr++ = chess ? 255 : 64; nuclear@17: *pptr++ = 128; nuclear@17: *pptr++ = chess ? 64 : 255; nuclear@17: *pptr++ = 255; /* alpha */ nuclear@17: } nuclear@17: } nuclear@17: } nuclear@17: nuclear@17: if(!tex->texid) { nuclear@17: glGenTextures(1, &tex->texid); nuclear@17: } nuclear@17: nuclear@17: glBindTexture(GL_TEXTURE_2D, tex->texid); nuclear@17: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); nuclear@17: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); nuclear@17: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, DBG_TEX_SZ, DBG_TEX_SZ, 0, GL_RGBA, nuclear@17: GL_UNSIGNED_BYTE, pixels); nuclear@17: nuclear@17: tex->width = tex->img_width = tex->height = tex->img_height = DBG_TEX_SZ; nuclear@17: return 0; nuclear@17: } nuclear@17: nuclear@17: nuclear@17: static size_t ioread(void *buf, size_t bytes, void *uptr) nuclear@17: { nuclear@17: return ass_fread(buf, 1, bytes, uptr); nuclear@17: } nuclear@17: nuclear@17: static long ioseek(long offs, int whence, void *uptr) nuclear@17: { nuclear@17: return ass_fseek(uptr, offs, whence); nuclear@17: } nuclear@17: nuclear@17: static unsigned int next_pow2(unsigned int x) nuclear@17: { nuclear@17: x--; nuclear@17: x = (x >> 1) | x; nuclear@17: x = (x >> 2) | x; nuclear@17: x = (x >> 4) | x; nuclear@17: x = (x >> 8) | x; nuclear@17: x = (x >> 16) | x; nuclear@17: return x + 1; nuclear@17: }