Newer
Older
#include <stdlib.h>
#include <stdio.h>
#ifdef WIN32
# include <windows.h>
# include <wingdi.h>
# define glBindTextureEXT glBindTexture
# define glGenTexturesEXT glGenTextures
#else /*unix?*/
#include <unistd.h>
#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 );
{
#if CAVE
/* assume virdir */
int id = CAT_get_display_slot();
if(id < 0 || id >= MAXDSPCTX) id = MAXDSPCTX-1;
return id;
#else /* stand-alone -- single GLX context */
return 0;
#endif
}
#define TEXTURENO(enab) ((enab) & 0xFFFFFF)
#define BLEND_ON 0x40000000
#define BLEND_OFF 0x20000000
int txbind( Texture *tx, int *enabled )
{
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
};
int wantblend = 0;
if(enabled == NULL || *enabled != 0) {
glBindTextureEXT( GL_TEXTURE_2D, 0 );
glDisable( GL_TEXTURE_2D );
glDisable( GL_ALPHA_TEST );
}
txenv = -1;
#if unix
if(tx->report & (1<<ctx)) {
fprintf(stderr, "tx %x pid %d ctx %d txid[ctx] %d data %x loaded %d isTexture %d\n",
tx, getpid(), ctx, tx->txid[ctx], tx->data, tx->loaded,
glIsTexture(tx->txid[ctx]));
tx->report &= ~(1<<ctx);
}
#endif
wantblend = (tx->flags & (TXF_ALPHA|TXF_INTENSITY)) ? BLEND_ON : BLEND_OFF;
wantenv =
tx->apply == TXF_DECAL ? GL_DECAL
: tx->apply == TXF_BLEND ? GL_BLEND
: GL_MODULATE;
if(txenv != wantenv) {
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, wantenv);
txenv = wantenv;
}
if(!mustload && TEXTURENO(*enabled) == tx->txid[ctx])
if(mustload) {
GLuint id;
glGenTexturesEXT( 1, &id );
tx->txid[ctx] = id;
}
wanted = tx->txid[ctx] | wantblend;
glBindTextureEXT( GL_TEXTURE_2D, TEXTURENO(wanted) );
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);
}
unsigned char *txdata = (unsigned char *)tx->data;
int channels = tx->channels;
if((tx->flags&TXF_INTENSITY) && (channels == 1 || channels == 3)) {
int npix = tx->xsize * tx->ysize;
int k;
unsigned char *ip, *op;
txdata = (unsigned char *)malloc( npix * channels );
k = npix;
ip = (unsigned char *)tx->data;
op = txdata;
switch(channels) {
case 2:
do {
op[1] = *ip++;
op[0] = 255;
op += 2;
} while(--k > 0);
break;
case 4:
do {
op[3] = 77*ip[0] + 150*ip[1] + 28*ip[2];
op[0] = ip[0]>=op[3] ? 255 : ip[0]/op[3];
op[1] = ip[1]>=op[3] ? 255 : ip[0]/op[3];
op[2] = ip[2]>=op[3] ? 255 : ip[2]/op[3];
ip += 3;
op += 4;
} while(--k > 0);
break;
}
}
gluBuild2DMipmaps( GL_TEXTURE_2D, channels,
channels==1 && (tx->flags&TXF_ALPHA)
? GL_ALPHA : format[channels],
GL_UNSIGNED_BYTE,
txdata);
if(txdata != (unsigned char *)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 & BLEND_ON) {
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glEnable( GL_ALPHA_TEST );
glAlphaFunc( GL_GREATER, 0.03 );
} else if(wanted & BLEND_OFF) {
glDisable( GL_BLEND );
glDisable(GL_ALPHA_TEST);
}
if(TEXTURENO(wanted)) {
glEnable(GL_TEXTURE_2D);
} else {
glDisable(GL_TEXTURE_2D);
}
*enabled = wanted = tx->txid[ctx] | wantblend;
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
}
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 *));
}