2006-05-16 14:52:36 +00:00
|
|
|
|
|
|
|
// Texture Manager
|
2005-01-12 15:20:02 +00:00
|
|
|
|
2008-01-26 11:47:23 +00:00
|
|
|
#include "engine/tinygl/zgl.h"
|
2005-01-12 15:20:02 +00:00
|
|
|
|
2006-05-16 14:52:36 +00:00
|
|
|
static GLTexture *find_texture(GLContext *c, int h) {
|
|
|
|
GLTexture *t;
|
2005-01-12 15:20:02 +00:00
|
|
|
|
2006-05-16 14:52:36 +00:00
|
|
|
t = c->shared_state.texture_hash_table[h % TEXTURE_HASH_TABLE_SIZE];
|
2008-09-10 11:16:57 +00:00
|
|
|
while (t) {
|
2006-05-16 14:52:36 +00:00
|
|
|
if (t->handle == h)
|
|
|
|
return t;
|
|
|
|
t = t->next;
|
|
|
|
}
|
|
|
|
return NULL;
|
2005-01-12 15:20:02 +00:00
|
|
|
}
|
|
|
|
|
2006-05-16 14:52:36 +00:00
|
|
|
static void free_texture(GLContext *c, int h) {
|
|
|
|
GLTexture *t, **ht;
|
|
|
|
GLImage *im;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
t = find_texture(c, h);
|
2008-07-29 19:28:19 +00:00
|
|
|
if (!t->prev) {
|
2006-05-16 14:52:36 +00:00
|
|
|
ht = &c->shared_state.texture_hash_table[t->handle % TEXTURE_HASH_TABLE_SIZE];
|
|
|
|
*ht = t->next;
|
|
|
|
} else {
|
|
|
|
t->prev->next = t->next;
|
|
|
|
}
|
2008-07-29 19:28:19 +00:00
|
|
|
if (t->next)
|
2006-05-16 14:52:36 +00:00
|
|
|
t->next->prev = t->prev;
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
|
|
|
|
im = &t->images[i];
|
2008-09-10 11:16:57 +00:00
|
|
|
if (im->pixmap)
|
2006-05-16 14:52:36 +00:00
|
|
|
gl_free(im->pixmap);
|
|
|
|
}
|
|
|
|
|
|
|
|
gl_free(t);
|
2005-01-12 15:20:02 +00:00
|
|
|
}
|
|
|
|
|
2008-07-29 19:28:19 +00:00
|
|
|
GLTexture *alloc_texture(GLContext *c, int h) {
|
|
|
|
GLTexture *t, **ht;
|
2005-01-12 15:20:02 +00:00
|
|
|
|
2008-07-29 19:28:19 +00:00
|
|
|
t = (GLTexture *)gl_zalloc(sizeof(GLTexture));
|
2005-01-12 15:20:02 +00:00
|
|
|
|
2008-07-29 19:28:19 +00:00
|
|
|
ht = &c->shared_state.texture_hash_table[h % TEXTURE_HASH_TABLE_SIZE];
|
2005-01-12 15:20:02 +00:00
|
|
|
|
2008-07-29 19:28:19 +00:00
|
|
|
t->next = *ht;
|
|
|
|
t->prev = NULL;
|
|
|
|
if (t->next)
|
|
|
|
t->next->prev = t;
|
|
|
|
*ht = t;
|
2005-01-12 15:20:02 +00:00
|
|
|
|
2008-07-29 19:28:19 +00:00
|
|
|
t->handle = h;
|
2005-01-12 15:20:02 +00:00
|
|
|
|
2008-07-29 19:28:19 +00:00
|
|
|
return t;
|
2005-01-12 15:20:02 +00:00
|
|
|
}
|
|
|
|
|
2008-07-29 19:28:19 +00:00
|
|
|
void glInitTextures(GLContext *c) {
|
|
|
|
// textures
|
|
|
|
c->texture_2d_enabled = 0;
|
|
|
|
c->current_texture = find_texture(c, 0);
|
2005-01-12 15:20:02 +00:00
|
|
|
}
|
|
|
|
|
2008-07-29 19:28:19 +00:00
|
|
|
void tglGenTextures(int n, unsigned int *textures) {
|
|
|
|
GLContext *c = gl_get_context();
|
|
|
|
int max, i;
|
|
|
|
GLTexture *t;
|
2005-01-12 15:20:02 +00:00
|
|
|
|
2008-07-29 19:28:19 +00:00
|
|
|
max = 0;
|
|
|
|
for (i = 0; i < TEXTURE_HASH_TABLE_SIZE; i++) {
|
|
|
|
t = c->shared_state.texture_hash_table[i];
|
|
|
|
while (t) {
|
|
|
|
if (t->handle > max)
|
|
|
|
max = t->handle;
|
|
|
|
t = t->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for(i = 0; i < n; i++) {
|
|
|
|
textures[i] = max + i + 1;
|
|
|
|
}
|
2005-01-12 15:20:02 +00:00
|
|
|
}
|
|
|
|
|
2008-07-29 19:28:19 +00:00
|
|
|
void tglDeleteTextures(int n, const unsigned int *textures) {
|
|
|
|
GLContext *c = gl_get_context();
|
|
|
|
int i;
|
|
|
|
GLTexture *t;
|
|
|
|
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
t = find_texture(c, textures[i]);
|
|
|
|
if (t) {
|
|
|
|
if (t == c->current_texture) {
|
|
|
|
tglBindTexture(TGL_TEXTURE_2D, 0);
|
|
|
|
}
|
|
|
|
free_texture(c, textures[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-01-12 15:20:02 +00:00
|
|
|
|
2008-07-29 19:28:19 +00:00
|
|
|
void glopBindTexture(GLContext *c, TGLParam *p) {
|
|
|
|
int target = p[1].i;
|
|
|
|
int texture = p[2].i;
|
|
|
|
GLTexture *t;
|
2005-01-12 15:20:02 +00:00
|
|
|
|
2008-07-29 19:28:19 +00:00
|
|
|
assert(target == TGL_TEXTURE_2D && texture >= 0);
|
2005-01-12 15:20:02 +00:00
|
|
|
|
2008-07-29 19:28:19 +00:00
|
|
|
t = find_texture(c, texture);
|
|
|
|
if (!t) {
|
|
|
|
t = alloc_texture(c, texture);
|
|
|
|
}
|
|
|
|
c->current_texture = t;
|
2005-01-12 15:20:02 +00:00
|
|
|
}
|
|
|
|
|
2008-07-13 21:03:12 +00:00
|
|
|
void glopTexImage2D(GLContext *c, TGLParam *p) {
|
|
|
|
int target = p[1].i;
|
|
|
|
int level = p[2].i;
|
|
|
|
int components = p[3].i;
|
|
|
|
int width = p[4].i;
|
|
|
|
int height = p[5].i;
|
|
|
|
int border = p[6].i;
|
|
|
|
int format = p[7].i;
|
|
|
|
int type = p[8].i;
|
|
|
|
void *pixels = p[9].p;
|
|
|
|
GLImage *im;
|
|
|
|
unsigned char *pixels1;
|
|
|
|
int do_free;
|
|
|
|
|
2008-07-29 19:28:19 +00:00
|
|
|
if (!(target == TGL_TEXTURE_2D && level == 0 && components == 3 && border == 0
|
|
|
|
&& format == TGL_RGBA && type == TGL_UNSIGNED_BYTE)) {
|
2008-09-28 19:09:23 +00:00
|
|
|
error("glTexImage2D: combination of parameters not handled");
|
2008-07-13 21:03:12 +00:00
|
|
|
}
|
2008-07-29 19:28:19 +00:00
|
|
|
|
2008-07-13 21:03:12 +00:00
|
|
|
do_free = 0;
|
|
|
|
if (width != 256 || height != 256) {
|
|
|
|
pixels1 = (unsigned char *)gl_malloc(256 * 256 * 4);
|
|
|
|
// no interpolation is done here to respect the original image aliasing !
|
|
|
|
//gl_resizeImageNoInterpolate(pixels1, 256, 256, (unsigned char *)pixels, width, height);
|
|
|
|
// used interpolation anyway, it look much better :) --- aquadran
|
|
|
|
gl_resizeImage(pixels1, 256, 256, (unsigned char *)pixels, width, height);
|
|
|
|
do_free = 1;
|
|
|
|
width = 256;
|
|
|
|
height = 256;
|
2008-07-29 19:28:19 +00:00
|
|
|
} else {
|
2008-07-13 21:03:12 +00:00
|
|
|
pixels1 = (unsigned char *)pixels;
|
2008-07-29 19:28:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
im = &c->current_texture->images[level];
|
|
|
|
im->xsize = width;
|
|
|
|
im->ysize = height;
|
|
|
|
if (im->pixmap)
|
|
|
|
gl_free(im->pixmap);
|
|
|
|
im->pixmap = gl_malloc(width * height * 3);
|
|
|
|
if (im->pixmap)
|
2008-07-13 21:03:12 +00:00
|
|
|
gl_convertRGB_to_5R6G5B8A((unsigned short *)im->pixmap, pixels1, width, height);
|
2008-07-29 19:28:19 +00:00
|
|
|
if (do_free)
|
2008-07-13 21:03:12 +00:00
|
|
|
gl_free(pixels1);
|
2005-01-12 15:20:02 +00:00
|
|
|
}
|
|
|
|
|
2008-07-29 19:28:19 +00:00
|
|
|
// TODO: not all tests are done
|
|
|
|
void glopTexEnv(GLContext *, TGLParam *p) {
|
|
|
|
int target = p[1].i;
|
|
|
|
int pname = p[2].i;
|
|
|
|
int param = p[3].i;
|
2005-01-12 15:20:02 +00:00
|
|
|
|
2008-07-29 19:28:19 +00:00
|
|
|
if (target != TGL_TEXTURE_ENV) {
|
|
|
|
error:
|
2008-09-28 19:09:23 +00:00
|
|
|
error("glTexParameter: unsupported option");
|
2008-07-29 19:28:19 +00:00
|
|
|
}
|
2005-01-12 15:20:02 +00:00
|
|
|
|
2008-07-29 19:28:19 +00:00
|
|
|
if (pname != TGL_TEXTURE_ENV_MODE)
|
|
|
|
goto error;
|
2005-01-12 15:20:02 +00:00
|
|
|
|
2008-07-29 19:28:19 +00:00
|
|
|
if (param != TGL_DECAL)
|
|
|
|
goto error;
|
2005-01-12 15:20:02 +00:00
|
|
|
}
|
|
|
|
|
2008-07-29 19:28:19 +00:00
|
|
|
// TODO: not all tests are done
|
|
|
|
void glopTexParameter(GLContext *, TGLParam *p) {
|
|
|
|
int target = p[1].i;
|
|
|
|
int pname = p[2].i;
|
|
|
|
int param = p[3].i;
|
|
|
|
|
|
|
|
if (target != TGL_TEXTURE_2D) {
|
|
|
|
error:
|
2008-09-28 19:09:23 +00:00
|
|
|
error("glTexParameter: unsupported option");
|
2008-07-29 19:28:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (pname) {
|
|
|
|
case TGL_TEXTURE_WRAP_S:
|
|
|
|
case TGL_TEXTURE_WRAP_T:
|
|
|
|
if (param != TGL_REPEAT)
|
|
|
|
goto error;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
;
|
|
|
|
}
|
2005-01-12 15:20:02 +00:00
|
|
|
}
|
|
|
|
|
2008-07-29 19:28:19 +00:00
|
|
|
void glopPixelStore(GLContext *, TGLParam *p) {
|
|
|
|
int pname = p[1].i;
|
|
|
|
int param = p[2].i;
|
2005-01-12 15:20:02 +00:00
|
|
|
|
2008-07-29 19:28:19 +00:00
|
|
|
if (pname != TGL_UNPACK_ALIGNMENT || param != 1) {
|
2008-09-28 19:09:23 +00:00
|
|
|
error("glPixelStore: unsupported option");
|
2008-07-29 19:28:19 +00:00
|
|
|
}
|
2005-01-12 15:20:02 +00:00
|
|
|
}
|