rev |
line source |
nuclear@17
|
1 #include <stdio.h>
|
nuclear@17
|
2 #include <stdlib.h>
|
nuclear@17
|
3 #include <string.h>
|
nuclear@17
|
4 #include <errno.h>
|
nuclear@17
|
5 #include <assert.h>
|
nuclear@17
|
6 #include "opengl.h"
|
nuclear@17
|
7 #include "texture.h"
|
nuclear@17
|
8 #include "imago2.h"
|
nuclear@17
|
9 #include "rbtree.h"
|
nuclear@17
|
10 #include "assman.h"
|
nuclear@17
|
11
|
nuclear@17
|
12 static size_t ioread(void *buf, size_t bytes, void *uptr);
|
nuclear@17
|
13 static long ioseek(long offs, int whence, void *uptr);
|
nuclear@17
|
14 static unsigned int next_pow2(unsigned int x);
|
nuclear@17
|
15
|
nuclear@17
|
16 static struct rbtree *texdb;
|
nuclear@17
|
17
|
nuclear@17
|
18 int load_texture(struct texture *tex, const char *fname)
|
nuclear@17
|
19 {
|
nuclear@17
|
20 struct img_pixmap img;
|
nuclear@17
|
21 struct img_io io;
|
nuclear@17
|
22 ass_file *fp;
|
nuclear@17
|
23
|
nuclear@17
|
24 printf("loading texture: %s\n", fname);
|
nuclear@17
|
25
|
nuclear@17
|
26 if(!(fp = ass_fopen(fname, "rb"))) {
|
nuclear@17
|
27 fprintf(stderr, "failed to open texture file: %s: %s\n", fname, strerror(errno));
|
nuclear@17
|
28 return -1;
|
nuclear@17
|
29 }
|
nuclear@17
|
30 io.uptr = fp;
|
nuclear@17
|
31 io.read = ioread;
|
nuclear@17
|
32 io.write = 0;
|
nuclear@17
|
33 io.seek = ioseek;
|
nuclear@17
|
34
|
nuclear@17
|
35 img_init(&img);
|
nuclear@17
|
36 if(img_read(&img, &io) == -1) {
|
nuclear@17
|
37 fprintf(stderr, "failed to load texture file: %s\n", fname);
|
nuclear@17
|
38 ass_fclose(fp);
|
nuclear@17
|
39 return -1;
|
nuclear@17
|
40 }
|
nuclear@17
|
41 img_convert(&img, IMG_FMT_RGBA32);
|
nuclear@17
|
42
|
nuclear@17
|
43 tex->img_width = img.width;
|
nuclear@17
|
44 tex->img_height = img.height;
|
nuclear@17
|
45 tex->width = next_pow2(img.width);
|
nuclear@17
|
46 tex->height = next_pow2(img.height);
|
nuclear@17
|
47
|
nuclear@17
|
48 printf(" %dx%d (tex: %dx%d)\n", tex->img_width, tex->img_height, tex->width, tex->height);
|
nuclear@17
|
49
|
nuclear@17
|
50 glGenTextures(1, &tex->texid);
|
nuclear@17
|
51 glBindTexture(GL_TEXTURE_2D, tex->texid);
|
nuclear@17
|
52 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
nuclear@17
|
53 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
nuclear@17
|
54
|
nuclear@17
|
55 #ifdef __GLEW_H__
|
nuclear@17
|
56 if(GLEW_SGIS_generate_mipmap) {
|
nuclear@17
|
57 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
|
nuclear@17
|
58 #endif
|
nuclear@17
|
59 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex->width, tex->height, 0,
|
nuclear@17
|
60 GL_RGBA, GL_UNSIGNED_BYTE, img.pixels);
|
nuclear@17
|
61 #ifdef __GLEW_H__
|
nuclear@17
|
62 } else {
|
nuclear@17
|
63 gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, tex->width, tex->height,
|
nuclear@17
|
64 GL_RGBA, GL_UNSIGNED_BYTE, img.pixels);
|
nuclear@17
|
65 }
|
nuclear@17
|
66 #endif
|
nuclear@17
|
67
|
nuclear@17
|
68 #ifdef GL_ES_VERSION_2_0
|
nuclear@17
|
69 glGenerateMipmap(GL_TEXTURE_2D);
|
nuclear@17
|
70 #endif
|
nuclear@17
|
71
|
nuclear@17
|
72 return 0;
|
nuclear@17
|
73 }
|
nuclear@17
|
74
|
nuclear@17
|
75 struct texture *get_texture(const char *fname)
|
nuclear@17
|
76 {
|
nuclear@17
|
77 struct texture *tex;
|
nuclear@17
|
78 struct rbnode *node;
|
nuclear@17
|
79
|
nuclear@17
|
80 if(!(texdb = rb_create(RB_KEY_STRING))) {
|
nuclear@17
|
81 static int err_printed;
|
nuclear@17
|
82 if(!err_printed) {
|
nuclear@17
|
83 fprintf(stderr, "failed to create texture database\n");
|
nuclear@17
|
84 err_printed = 1;
|
nuclear@17
|
85 }
|
nuclear@17
|
86 return 0;
|
nuclear@17
|
87 }
|
nuclear@17
|
88
|
nuclear@17
|
89 if((node = rb_find(texdb, (void*)fname))) {
|
nuclear@17
|
90 return rb_node_data(node);
|
nuclear@17
|
91 }
|
nuclear@17
|
92
|
nuclear@17
|
93 if(!(tex = malloc(sizeof *tex))) {
|
nuclear@17
|
94 fprintf(stderr, "failed to load texture \"%s\": %s\n", fname, strerror(errno));
|
nuclear@17
|
95 return 0;
|
nuclear@17
|
96 }
|
nuclear@17
|
97 if(load_texture(tex, fname) == -1) {
|
nuclear@17
|
98 free(tex);
|
nuclear@17
|
99 return 0;
|
nuclear@17
|
100 }
|
nuclear@17
|
101
|
nuclear@17
|
102 if(rb_insert(texdb, (void*)fname, tex) == -1) {
|
nuclear@17
|
103 fprintf(stderr, "failed to insert texture into the texture database\n");
|
nuclear@17
|
104 }
|
nuclear@17
|
105 return tex;
|
nuclear@17
|
106 }
|
nuclear@17
|
107
|
nuclear@17
|
108
|
nuclear@17
|
109 #define DBG_TEX_SZ 64
|
nuclear@17
|
110 int gen_debug_texture(struct texture *tex)
|
nuclear@17
|
111 {
|
nuclear@17
|
112 static unsigned char *pixels;
|
nuclear@17
|
113
|
nuclear@17
|
114 if(!pixels) {
|
nuclear@17
|
115 int i, j;
|
nuclear@17
|
116 unsigned char *pptr;
|
nuclear@17
|
117 pptr = pixels = malloc(DBG_TEX_SZ * DBG_TEX_SZ * 4);
|
nuclear@17
|
118 assert(pixels);
|
nuclear@17
|
119
|
nuclear@17
|
120 for(i=0; i<DBG_TEX_SZ; i++) {
|
nuclear@17
|
121 for(j=0; j<DBG_TEX_SZ; j++) {
|
nuclear@17
|
122 int chess = ((j >> 3) & 1) == ((i >> 3) & 1);
|
nuclear@17
|
123 *pptr++ = chess ? 255 : 64;
|
nuclear@17
|
124 *pptr++ = 128;
|
nuclear@17
|
125 *pptr++ = chess ? 64 : 255;
|
nuclear@17
|
126 *pptr++ = 255; /* alpha */
|
nuclear@17
|
127 }
|
nuclear@17
|
128 }
|
nuclear@17
|
129 }
|
nuclear@17
|
130
|
nuclear@17
|
131 if(!tex->texid) {
|
nuclear@17
|
132 glGenTextures(1, &tex->texid);
|
nuclear@17
|
133 }
|
nuclear@17
|
134
|
nuclear@17
|
135 glBindTexture(GL_TEXTURE_2D, tex->texid);
|
nuclear@17
|
136 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
nuclear@17
|
137 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
nuclear@17
|
138 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, DBG_TEX_SZ, DBG_TEX_SZ, 0, GL_RGBA,
|
nuclear@17
|
139 GL_UNSIGNED_BYTE, pixels);
|
nuclear@17
|
140
|
nuclear@17
|
141 tex->width = tex->img_width = tex->height = tex->img_height = DBG_TEX_SZ;
|
nuclear@17
|
142 return 0;
|
nuclear@17
|
143 }
|
nuclear@17
|
144
|
nuclear@17
|
145
|
nuclear@17
|
146 static size_t ioread(void *buf, size_t bytes, void *uptr)
|
nuclear@17
|
147 {
|
nuclear@17
|
148 return ass_fread(buf, 1, bytes, uptr);
|
nuclear@17
|
149 }
|
nuclear@17
|
150
|
nuclear@17
|
151 static long ioseek(long offs, int whence, void *uptr)
|
nuclear@17
|
152 {
|
nuclear@17
|
153 return ass_fseek(uptr, offs, whence);
|
nuclear@17
|
154 }
|
nuclear@17
|
155
|
nuclear@17
|
156 static unsigned int next_pow2(unsigned int x)
|
nuclear@17
|
157 {
|
nuclear@17
|
158 x--;
|
nuclear@17
|
159 x = (x >> 1) | x;
|
nuclear@17
|
160 x = (x >> 2) | x;
|
nuclear@17
|
161 x = (x >> 4) | x;
|
nuclear@17
|
162 x = (x >> 8) | x;
|
nuclear@17
|
163 x = (x >> 16) | x;
|
nuclear@17
|
164 return x + 1;
|
nuclear@17
|
165 }
|