textures.c 4.20 KiB
#include <stdlib.h>
#include <stdio.h>
#ifdef WIN32
# include <windows.h>
# include <wingdi.h>
# define glBindTextureEXT glBindTexture
# define glGenTexturesEXT glGenTextures
#endif /*WIN32*/
#include <GL/gl.h>
#include <GL/glu.h>
#include <string.h>
#include "textures.h"
#include "shmem.h"
#include "findfile.h"
#if CAVE
#include "vd_util.h"
#endif
extern int mg_inhaletexture( Texture *tx, int rgba );
int my_txcontext(void)
{
#if CAVE
/* assume virdir */
int id = CAT_get_display_slot();
if(id < 0 || id >= MAXGLCTX) id = MAXGLCTX-1;
return id;
#else /* stand-alone -- single GLX context */
return 0;
#endif
}
int txbind( Texture *tx, int *enabled )
{
int ena = -1;
int ctx;
int mustload;
int wanted;
static GLint format[5] =
{ 0, GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA };
static GLfloat minfilts[] = {
GL_NEAREST, GL_LINEAR,
GL_NEAREST, GL_LINEAR,
GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR,
GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR
};
if(enabled == NULL) enabled = &ena;
if(tx == NULL || txload(tx) == 0) {
glBindTextureEXT( GL_TEXTURE_2D, 0 );
if(*enabled != 0) glDisable(GL_TEXTURE_2D);
*enabled = 0;
return 0;
}
ctx = my_txcontext();
mustload = (tx->txid[ctx] == 0);
if(mustload) {
GLuint id;
glGenTexturesEXT( 1, &id );
tx->txid[ctx] = id;
}
glBindTextureEXT( GL_TEXTURE_2D, tx->txid[ctx] );
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
tx->apply == TXF_DECAL ? GL_DECAL
: tx->apply == TXF_BLEND ? GL_BLEND : GL_MODULATE);
wanted = 1;
if(mustload) {
if(tx->data == NULL) {
fprintf(stderr,
"Hey! Why are we having to reload the data for texture \"%s\"?\n",
tx->filename);
tx->loaded = 0;
txload(tx);
wanted = (tx->data != NULL);
}
if(wanted) {
static float black[4] = {0,0,0,0};
gluBuild2DMipmaps( GL_TEXTURE_2D, tx->channels,
tx->xsize, tx->ysize,
format[tx->channels], GL_UNSIGNED_BYTE,
(unsigned long *)tx->data);
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR,
black);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
(tx->flags & TXF_SCLAMP) ? GL_CLAMP : GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
(tx->flags & TXF_TCLAMP) ? GL_CLAMP : GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
minfilts[tx->qualflags & 0x07]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
(tx->qualflags&0x07) ? GL_LINEAR : GL_NEAREST);
#if !CAVE
/* We won't need texture data again -- opengl has it now */
Free(tx->data);
tx->data = NULL;
#endif
}
}
if(wanted != *enabled) {
if(wanted) glEnable(GL_TEXTURE_2D);
else glDisable(GL_TEXTURE_2D);
*enabled = wanted;
}
return wanted;
}
Texture *txmake( char *fname, int apply, int txflags, int qualflags )
{
Texture *tx = NewN( Texture, 1 );
memset(tx, 0, sizeof(*tx));
tx->tfm = Tidentity;
tx->filename = fname;
tx->apply = apply;
tx->flags = txflags;
tx->qualflags = qualflags;
return tx;
}
int txload( Texture *tx )
{
if(tx == NULL || tx->loaded < 0) return 0;
if(tx->loaded == 1) return 1; /* already loaded */
if(tx->loaded == 2) return 0; /* busy loading now! */
tx->loaded = 2; /* set this to make multiprocess collisions unlikely */
if(mg_inhaletexture( tx, TXF_RGBA ) <= 0) {
tx->loaded = -1;
return 0;
}
tx->loaded = 1;
return 1;
}
int txaddentry( Texture ***tp, int *ntextures, char *fromfile,
int txno, char *txfname, int apply, int txflags, int qualflags )
{
char *realfname;
if(txno <= 0) {
fprintf(stderr, "Texture indices must be > 0 (texture %d %s)\n", txno, txfname);
return 0;
}
realfname = findfile(fromfile, txfname);
if(realfname == NULL) {
fprintf(stderr, "Can't find texture file \"%s\", ignoring it.\n", txfname);
return 0;
}
if(txno >= *ntextures) {
int ontex = *ntextures;
if(*ntextures == 0) {
*ntextures = txno + 62;
*tp = NewN( Texture *, *ntextures );
} else {
*ntextures = (txno > ontex*2+1 ? txno+ontex : ontex*2+1);
*tp = RenewN( *tp, Texture *, *ntextures );
}
memset(&(*tp)[ontex], 0, (*ntextures - ontex) * sizeof(Texture *));
}
(*tp)[txno-1] = txmake( shmstrdup(realfname), apply, txflags, qualflags );
return txno;
}