modify logging to simplify i18n
[voxelands-alt.git] / src / graphics / texture.c
blob096c5d50dfeadff6e1b26eedbba9e6fca066822a
1 /************************************************************************
2 * texture.c
3 * voxelands - 3d voxel world sandbox game
4 * Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>
18 ************************************************************************/
20 #include "common.h"
21 #include "graphics.h"
22 #include "list.h"
24 #include <string.h>
26 static texture_t *textures = NULL;
27 static int tex_ids = 0;
29 /* generate the hardware texture */
30 int tex_generate(texture_t *tex)
32 int b = 0;
33 int t = 0;
34 int m = 0;
35 GLenum e;
36 if (!tex)
37 return 1;
39 /* delete the old texture, if it exists */
40 if (tex->state) {
41 glDeleteTextures(1, &tex->glid);
42 e = glGetError();
43 if (e != GL_NO_ERROR) {
44 char* es = opengl_error_string(e);
45 vlprintf(CN_ERROR, "%s",es);
46 return 1;
50 /* create a new texture */
51 glGenTextures(1, &tex->glid);
52 e = glGetError();
53 if (e != GL_NO_ERROR) {
54 char* es = opengl_error_string(e);
55 vlprintf(CN_ERROR, "%s",es);
56 return 1;
59 glBindTexture(GL_TEXTURE_2D, tex->glid);
60 e = glGetError();
61 if (e != GL_NO_ERROR) {
62 char* es = opengl_error_string(e);
63 vlprintf(CN_ERROR, "%s",es);
64 return 1;
67 b = opengl_has_bilinear();
68 t = opengl_has_trilinear();
69 m = opengl_has_mipmap();
71 /* draw the pixels to the texture */
72 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex->px->w, tex->px->h , 0, GL_RGBA, GL_UNSIGNED_BYTE, tex->px->pixels);
73 e = glGetError();
74 if (e != GL_NO_ERROR) {
75 char* es = opengl_error_string(e);
76 vlprintf(CN_ERROR, "%s",es);
77 return 1;
80 if (m) {
81 /* shouldn't ever need this, but there's an ATI/AMD bug that this fixes */
82 glEnable(GL_TEXTURE_2D);
83 glGenerateMipmap(GL_TEXTURE_2D);
84 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
85 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
88 if (t) {
89 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
90 if (m) {
91 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
92 }else{
93 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
95 }else if (b) {
96 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
97 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
98 }else{
99 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
100 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
103 if (opengl_has_anisotropic()) {
104 float ma = opengl_max_anisotropic();
105 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, ma);
108 e = glGetError();
109 if (e != GL_NO_ERROR) {
110 char* es = opengl_error_string(e);
111 vlprintf(CN_ERROR, "%s",es);
112 return 1;
115 tex->state = 1;
117 return 0;
120 /* add a new image to the cache */
121 texture_t *tex_create()
123 texture_t *tex = malloc(sizeof(texture_t));
124 if (tex == NULL)
125 return NULL;
127 tex->w = 0;
128 tex->h = 0;
129 tex->xf = 0;
130 tex->yf = 0;
131 tex->name[0] = 0;
132 tex->px = NULL;
133 tex->id = tex_ids++;
134 tex->glid = 0;
135 tex->state = 0;
137 textures = list_push(&textures,tex);
139 return tex;
142 /* free a texture */
143 void tex_free(texture_t *tex)
145 if (!tex)
146 return;
147 textures = list_remove(&textures,tex);
148 if (tex->glid)
149 glDeleteTextures(1, &tex->glid);
150 free(tex);
153 /* load an image to a texture */
154 texture_t *tex_from_image(char* type, char* file)
156 texture_t *t;
157 /* get the image */
158 image_t *p;
160 t = textures;
161 while (t) {
162 if (!strcmp(t->name,file))
163 break;
164 t = t->next;
167 if (t)
168 return t;
170 p = image_load(type,file);
171 if (!p)
172 return NULL;
174 /* and make a texture out of it */
175 t = tex_from_pixels(p);
176 if (t)
177 strncpy(t->name,file,100);
179 return t;
182 /* create a texture from pixel data */
183 texture_t *tex_from_pixels(image_t *px)
185 texture_t *tex;
186 if (!px)
187 return NULL;
189 tex = tex_create();
190 if (tex == NULL)
191 return NULL;
193 tex->w = px->w;
194 tex->h = px->h ;
195 tex->px = px;
196 tex->xf = 1.0/(GLfloat)px->w;
197 tex->yf = 1.0/(GLfloat)px->h;
199 if (!tex_generate(tex))
200 return tex;
202 tex_free(tex);
204 return NULL;
207 /* update a texture from pixel data */
208 texture_t *tex_update_pixels(texture_t *tex, image_t *px)
210 if (!tex)
211 return tex_from_pixels(px);
213 tex->w = px->w;
214 tex->h = px->h ;
215 tex->px = px;
216 tex->xf = 1.0/(GLfloat)px->w;
217 tex->yf = 1.0/(GLfloat)px->h;
219 if (!tex_generate(tex))
220 return tex;
222 tex_free(tex);
224 return NULL;
227 /* create a transparent texture */
228 texture_t *tex_from_rgba(int x, int y, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
230 char n[100];
231 texture_t *t;
232 image_t *p;
234 snprintf(n,100,"rgba-%u-%u-%u-%u-%d-%d",(uint32_t)r,(uint32_t)g,(uint32_t)b,(uint32_t)a,x,y);
235 t = textures;
236 while (t) {
237 if (!strcmp(t->name,n))
238 break;
239 t = t->next;
242 if (t)
243 return t;
245 p = image_rgba(x,y,r,g,b,a);
246 if (!p)
247 return NULL;
249 t = tex_from_pixels(p);
250 strcpy(t->name,n);
252 return t;