dvr/app/jni/prboom/gl_texture.c

982 lines
29 KiB
C
Raw Normal View History

2016-03-03 22:28:59 +00:00
/* Emacs style mode select -*- C++ -*-
*-----------------------------------------------------------------------------
*
*
* PrBoom: a Doom port merged with LxDoom and LSDLDoom
* based on BOOM, a modified and improved DOOM engine
* Copyright (C) 1999 by
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
* Copyright (C) 1999-2000 by
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
* Copyright 2005, 2006 by
* Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* DESCRIPTION:
*
*---------------------------------------------------------------------
*/
#include "z_zone.h"
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#ifndef CALLBACK
#define CALLBACK
#endif
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <SDL.h>
#include <SDL_opengles.h>
#include "doomtype.h"
#include "w_wad.h"
#include "m_argv.h"
#include "d_event.h"
#include "v_video.h"
#include "doomstat.h"
#include "r_bsp.h"
#include "r_main.h"
#include "r_draw.h"
#include "r_sky.h"
#include "r_plane.h"
#include "r_data.h"
#include "p_maputl.h"
#include "p_tick.h"
#include "m_bbox.h"
#include "lprintf.h"
#include "gl_intern.h"
#include "gl_struct.h"
/* TEXTURES */
static GLTexture **gld_GLTextures=NULL;
/* PATCHES FLATS SPRITES */
static GLTexture **gld_GLPatchTextures=NULL;
boolean use_mipmapping=false;
int gld_max_texturesize=0;
char *gl_tex_format_string;
int gl_tex_format=GL_RGB;
//int gl_tex_format=GL_RGB5_A1;
//int gl_tex_format=GL_RGBA4;
//int gl_tex_format=GL_RGBA2;
GLTexture *last_gltexture=NULL;
int last_cm=-1;
int transparent_pal_index;
unsigned char gld_palmap[256];
void gld_InitPalettedTextures(void)
{
const unsigned char *playpal;
int pal[256];
int i,j;
playpal=W_CacheLumpName("PLAYPAL");
for (i=0; i<256; i++) {
pal[i] = (playpal[i*3+0] << 16) | (playpal[i*3+1] << 8) | playpal[i*3+2];
gld_palmap[i] = i;
}
transparent_pal_index = -1;
for (i=0; i<256; i++) {
for (j=i+1; j<256; j++) {
if (pal[i] == pal[j]) {
transparent_pal_index = j;
gld_palmap[j] = i;
break;
}
}
if (transparent_pal_index >= 0)
break;
}
W_UnlockLumpName("PLAYPAL");
}
int gld_GetTexDimension(int value)
{
int i;
i=1;
while (i<value)
i*=2;
if (i>gld_max_texturesize)
i=gld_max_texturesize;
return i;
}
static GLTexture *gld_AddNewGLTexture(int texture_num)
{
if (texture_num<0)
return NULL;
if (texture_num>=numtextures)
return NULL;
if (!gld_GLTextures)
{
gld_GLTextures=Z_Malloc(numtextures*sizeof(GLTexture *),PU_STATIC,0);
memset(gld_GLTextures,0,numtextures*sizeof(GLTexture *));
}
if (!gld_GLTextures[texture_num])
{
gld_GLTextures[texture_num]=Z_Malloc(sizeof(GLTexture),PU_STATIC,0);
memset(gld_GLTextures[texture_num], 0, sizeof(GLTexture));
gld_GLTextures[texture_num]->textype=GLDT_UNREGISTERED;
}
return gld_GLTextures[texture_num];
}
static GLTexture *gld_AddNewGLPatchTexture(int lump)
{
if (lump<0)
return NULL;
if (lump>=numlumps)
return NULL;
if (!gld_GLPatchTextures)
{
gld_GLPatchTextures=Z_Malloc(numlumps*sizeof(GLTexture *),PU_STATIC,0);
memset(gld_GLPatchTextures,0,numlumps*sizeof(GLTexture *));
}
if (!gld_GLPatchTextures[lump])
{
gld_GLPatchTextures[lump]=Z_Malloc(sizeof(GLTexture),PU_STATIC,0);
memset(gld_GLPatchTextures[lump], 0, sizeof(GLTexture));
gld_GLPatchTextures[lump]->textype=GLDT_UNREGISTERED;
}
return gld_GLPatchTextures[lump];
}
void gld_SetTexturePalette(GLenum target)
{
#ifndef GL_VERSION_ES_CM_1_0
const unsigned char *playpal;
unsigned char pal[1024];
int i;
playpal=W_CacheLumpName("PLAYPAL");
for (i=0; i<256; i++) {
pal[i*4+0] = playpal[i*3+0];
pal[i*4+1] = playpal[i*3+1];
pal[i*4+2] = playpal[i*3+2];
pal[i*4+3] = 255;
}
pal[transparent_pal_index*4+0]=0;
pal[transparent_pal_index*4+1]=0;
pal[transparent_pal_index*4+2]=0;
pal[transparent_pal_index*4+3]=0;
gld_ColorTableEXT(target, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, pal);
W_UnlockLumpName("PLAYPAL");
#endif
}
static void gld_AddPatchToTexture_UnTranslated(GLTexture *gltexture, unsigned char *buffer, const rpatch_t *patch, int originx, int originy, int paletted)
{
int x,y,j;
int xs,xe;
int js,je;
const rcolumn_t *column;
const byte *source;
int i, pos;
const unsigned char *playpal;
if (!gltexture)
return;
if (!patch)
return;
playpal=W_CacheLumpName("PLAYPAL");
xs=0;
xe=patch->width;
if ((xs+originx)>=gltexture->realtexwidth)
return;
if ((xe+originx)<=0)
return;
if ((xs+originx)<0)
xs=-originx;
if ((xe+originx)>gltexture->realtexwidth)
xe+=(gltexture->realtexwidth-(xe+originx));
for (x=xs;x<xe;x++)
{
#ifdef RANGECHECK
if (x>=patch->width)
{
lprintf(LO_ERROR,"gld_AddPatchToTexture_UnTranslated x>=patch->width (%i >= %i)\n",x,patch->width);
return;
}
#endif
column = &patch->columns[x];
for (i=0; i<column->numPosts; i++) {
const rpost_t *post = &column->posts[i];
y=(post->topdelta+originy);
js=0;
je=post->length;
if ((js+y)>=gltexture->realtexheight)
continue;
if ((je+y)<=0)
continue;
if ((js+y)<0)
js=-y;
if ((je+y)>gltexture->realtexheight)
je+=(gltexture->realtexheight-(je+y));
source = column->pixels + post->topdelta;
if (paletted) {
pos=(((js+y)*gltexture->buffer_width)+x+originx);
for (j=js;j<je;j++,pos+=(gltexture->buffer_width))
{
#ifdef RANGECHECK
if (pos>=gltexture->buffer_size)
{
lprintf(LO_ERROR,"gld_AddPatchToTexture_UnTranslated pos>=size (%i >= %i)\n",pos+3,gltexture->buffer_size);
return;
}
#endif
buffer[pos]=gld_palmap[source[j]];
}
} else {
pos=4*(((js+y)*gltexture->buffer_width)+x+originx);
for (j=js;j<je;j++,pos+=(4*gltexture->buffer_width))
{
#ifdef RANGECHECK
if ((pos+3)>=gltexture->buffer_size)
{
lprintf(LO_ERROR,"gld_AddPatchToTexture_UnTranslated pos+3>=size (%i >= %i)\n",pos+3,gltexture->buffer_size);
return;
}
#endif
buffer[pos]=playpal[source[j]*3];
buffer[pos+1]=playpal[source[j]*3+1];
buffer[pos+2]=playpal[source[j]*3+2];
buffer[pos+3]=255;
}
}
}
}
W_UnlockLumpName("PLAYPAL");
}
void gld_AddPatchToTexture(GLTexture *gltexture, unsigned char *buffer, const rpatch_t *patch, int originx, int originy, int cm, int paletted)
{
int x,y,j;
int xs,xe;
int js,je;
const rcolumn_t *column;
const byte *source;
int i, pos;
const unsigned char *playpal;
const unsigned char *outr;
if (!gltexture)
return;
if (!patch)
return;
if ((cm==CR_DEFAULT) || (cm==CR_LIMIT))
{
gld_AddPatchToTexture_UnTranslated(gltexture,buffer,patch,originx,originy, paletted);
return;
}
if (cm<CR_LIMIT)
outr=colrngs[cm];
else
outr=translationtables + 256*((cm-CR_LIMIT)-1);
playpal=W_CacheLumpName("PLAYPAL");
xs=0;
xe=patch->width;
if ((xs+originx)>=gltexture->realtexwidth)
return;
if ((xe+originx)<=0)
return;
if ((xs+originx)<0)
xs=-originx;
if ((xe+originx)>gltexture->realtexwidth)
xe+=(gltexture->realtexwidth-(xe+originx));
for (x=xs;x<xe;x++)
{
#ifdef RANGECHECK
if (x>=patch->width)
{
lprintf(LO_ERROR,"gld_AddPatchToTexture x>=patch->width (%i >= %i)\n",x,patch->width);
return;
}
#endif
column = &patch->columns[x];
for (i=0; i<column->numPosts; i++) {
const rpost_t *post = &column->posts[i];
y=(post->topdelta+originy);
js=0;
je=post->length;
if ((js+y)>=gltexture->realtexheight)
continue;
if ((je+y)<=0)
continue;
if ((js+y)<0)
js=-y;
if ((je+y)>gltexture->realtexheight)
je+=(gltexture->realtexheight-(je+y));
source = column->pixels + post->topdelta;
if (paletted) {
pos=(((js+y)*gltexture->buffer_width)+x+originx);
for (j=js;j<je;j++,pos+=(gltexture->buffer_width))
{
#ifdef RANGECHECK
if (pos>=gltexture->buffer_size)
{
lprintf(LO_ERROR,"gld_AddPatchToTexture_UnTranslated pos>=size (%i >= %i)\n",pos+3,gltexture->buffer_size);
return;
}
#endif
buffer[pos]=gld_palmap[outr[source[j]]];
}
} else {
pos=4*(((js+y)*gltexture->buffer_width)+x+originx);
for (j=js;j<je;j++,pos+=(4*gltexture->buffer_width))
{
#ifdef RANGECHECK
if ((pos+3)>=gltexture->buffer_size)
{
lprintf(LO_ERROR,"gld_AddPatchToTexture pos+3>=size (%i >= %i)\n",pos+3,gltexture->buffer_size);
return;
}
#endif
buffer[pos]=playpal[outr[source[j]]*3];
buffer[pos+1]=playpal[outr[source[j]]*3+1];
buffer[pos+2]=playpal[outr[source[j]]*3+2];
buffer[pos+3]=255;
}
}
}
}
W_UnlockLumpName("PLAYPAL");
}
static void gld_AddFlatToTexture(GLTexture *gltexture, unsigned char *buffer, const unsigned char *flat, int paletted)
{
int x,y,pos;
const unsigned char *playpal;
if (!gltexture)
return;
if (!flat)
return;
if (paletted) {
for (y=0;y<gltexture->realtexheight;y++)
{
pos=(y*gltexture->buffer_width);
for (x=0;x<gltexture->realtexwidth;x++,pos++)
{
#ifdef RANGECHECK
if (pos>=gltexture->buffer_size)
{
lprintf(LO_ERROR,"gld_AddFlatToTexture pos>=size (%i >= %i)\n",pos,gltexture->buffer_size);
return;
}
#endif
buffer[pos]=gld_palmap[flat[y*64+x]];
}
}
} else {
playpal=W_CacheLumpName("PLAYPAL");
for (y=0;y<gltexture->realtexheight;y++)
{
pos=4*(y*gltexture->buffer_width);
for (x=0;x<gltexture->realtexwidth;x++,pos+=4)
{
#ifdef RANGECHECK
if ((pos+3)>=gltexture->buffer_size)
{
lprintf(LO_ERROR,"gld_AddFlatToTexture pos+3>=size (%i >= %i)\n",pos+3,gltexture->buffer_size);
return;
}
#endif
buffer[pos]=playpal[flat[y*64+x]*3];
buffer[pos+1]=playpal[flat[y*64+x]*3+1];
buffer[pos+2]=playpal[flat[y*64+x]*3+2];
buffer[pos+3]=255;
}
}
W_UnlockLumpName("PLAYPAL");
}
}
//e6y: "force" flag for loading texture with zero index
GLTexture *gld_RegisterTexture(int texture_num, boolean mipmap, boolean force)
{
GLTexture *gltexture;
//e6y: textures with zero index should be loaded sometimes
if (texture_num==NO_TEXTURE && !force)
return NULL;
gltexture=gld_AddNewGLTexture(texture_num);
if (!gltexture)
return NULL;
if (gltexture->textype==GLDT_UNREGISTERED)
{
texture_t *texture=NULL;
if ((texture_num>=0) || (texture_num<numtextures))
texture=textures[texture_num];
if (!texture)
return NULL;
gltexture->textype=GLDT_BROKEN;
gltexture->index=texture_num;
gltexture->mipmap=mipmap;
gltexture->realtexwidth=texture->width;
gltexture->realtexheight=texture->height;
gltexture->leftoffset=0;
gltexture->topoffset=0;
gltexture->tex_width=gld_GetTexDimension(gltexture->realtexwidth);
gltexture->tex_height=gld_GetTexDimension(gltexture->realtexheight);
gltexture->width=MIN(gltexture->realtexwidth, gltexture->tex_width);
gltexture->height=MIN(gltexture->realtexheight, gltexture->tex_height);
gltexture->buffer_width=gltexture->tex_width;
gltexture->buffer_height=gltexture->tex_height;
#ifdef USE_GLU_IMAGESCALE
gltexture->width=gltexture->tex_width;
gltexture->height=gltexture->tex_height;
gltexture->buffer_width=gltexture->realtexwidth;
gltexture->buffer_height=gltexture->realtexheight;
#endif
if (gltexture->mipmap & use_mipmapping)
{
gltexture->width=gltexture->tex_width;
gltexture->height=gltexture->tex_height;
gltexture->buffer_width=gltexture->realtexwidth;
gltexture->buffer_height=gltexture->realtexheight;
}
gltexture->buffer_size=gltexture->buffer_width*gltexture->buffer_height*4;
if (gltexture->realtexwidth>gltexture->buffer_width)
return gltexture;
if (gltexture->realtexheight>gltexture->buffer_height)
return gltexture;
gltexture->textype=GLDT_TEXTURE;
}
return gltexture;
}
void gld_BindTexture(GLTexture *gltexture)
{
const rpatch_t *patch;
int i;
unsigned char *buffer;
if (gltexture==last_gltexture)
return;
last_gltexture=gltexture;
if (!gltexture) {
glBindTexture(GL_TEXTURE_2D, 0);
last_gltexture = NULL;
last_cm = -1;
return;
}
if (gltexture->textype!=GLDT_TEXTURE)
{
glBindTexture(GL_TEXTURE_2D, 0);
last_gltexture = NULL;
last_cm = -1;
return;
}
if (gltexture->glTexID[CR_DEFAULT]!=0)
{
glBindTexture(GL_TEXTURE_2D, gltexture->glTexID[CR_DEFAULT]);
#ifndef GL_VERSION_ES_CM_1_0
glGetTexParameteriv(GL_TEXTURE_2D,GL_TEXTURE_RESIDENT,&i);
#ifdef _DEBUG
if (i!=GL_TRUE)
lprintf(LO_INFO, "glGetTexParam: %i\n", i);
#endif
if (i==GL_TRUE)
return;
#endif
}
buffer=(unsigned char*)Z_Malloc(gltexture->buffer_size,PU_STATIC,0);
if (!(gltexture->mipmap & use_mipmapping) & gl_paletted_texture)
memset(buffer,transparent_pal_index,gltexture->buffer_size);
else
memset(buffer,0,gltexture->buffer_size);
patch=R_CacheTextureCompositePatchNum(gltexture->index);
gld_AddPatchToTexture(gltexture, buffer, patch,
0, 0,
CR_DEFAULT, !(gltexture->mipmap & use_mipmapping) & gl_paletted_texture);
R_UnlockTextureCompositePatchNum(gltexture->index);
if (gltexture->glTexID[CR_DEFAULT]==0)
glGenTextures(1,&gltexture->glTexID[CR_DEFAULT]);
glBindTexture(GL_TEXTURE_2D, gltexture->glTexID[CR_DEFAULT]);
#ifdef USE_GLU_MIPMAP
if (gltexture->mipmap & use_mipmapping)
{
gluBuild2DMipmaps(GL_TEXTURE_2D, gl_tex_format,
gltexture->buffer_width, gltexture->buffer_height,
GL_RGBA, GL_UNSIGNED_BYTE, buffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_tex_filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_mipmap_filter);
if (gl_texture_filter_anisotropic)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2.0);
}
else
#endif /* USE_GLU_MIPMAP */
{
#ifdef USE_GLU_IMAGESCALE
if ((gltexture->buffer_width!=gltexture->tex_width) ||
(gltexture->buffer_height!=gltexture->tex_height)
)
{
unsigned char *scaledbuffer;
scaledbuffer=(unsigned char*)Z_Malloc(gltexture->tex_width*gltexture->tex_height*4,PU_STATIC,0);
if (scaledbuffer)
{
gluScaleImage(GL_RGBA,
gltexture->buffer_width, gltexture->buffer_height,
GL_UNSIGNED_BYTE,buffer,
gltexture->tex_width, gltexture->tex_height,
GL_UNSIGNED_BYTE,scaledbuffer);
Z_Free(buffer);
buffer=scaledbuffer;
glTexImage2D( GL_TEXTURE_2D, 0, gl_tex_format,
gltexture->tex_width, gltexture->tex_height,
0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
}
}
else
#endif /* USE_GLU_IMAGESCALE */
{
if (gl_paletted_texture) {
#ifndef GL_VERSION_ES_CM_1_0
gld_SetTexturePalette(GL_TEXTURE_2D);
glTexImage2D( GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT,
gltexture->buffer_width, gltexture->buffer_height,
0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, buffer);
#endif
} else {
glTexImage2D( GL_TEXTURE_2D, 0, gl_tex_format,
gltexture->buffer_width, gltexture->buffer_height,
0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
}
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_tex_filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_tex_filter);
}
Z_Free(buffer);
}
GLTexture *gld_RegisterPatch(int lump, int cm)
{
const rpatch_t *patch;
GLTexture *gltexture;
gltexture=gld_AddNewGLPatchTexture(lump);
if (!gltexture)
return NULL;
if (gltexture->textype==GLDT_UNREGISTERED)
{
patch=R_CachePatchNum(lump);
if (!patch)
return NULL;
gltexture->textype=GLDT_BROKEN;
gltexture->index=lump;
gltexture->mipmap=false;
gltexture->realtexwidth=patch->width;
gltexture->realtexheight=patch->height;
gltexture->leftoffset=patch->leftoffset;
gltexture->topoffset=patch->topoffset;
gltexture->tex_width=gld_GetTexDimension(gltexture->realtexwidth);
gltexture->tex_height=gld_GetTexDimension(gltexture->realtexheight);
gltexture->width=MIN(gltexture->realtexwidth, gltexture->tex_width);
gltexture->height=MIN(gltexture->realtexheight, gltexture->tex_height);
gltexture->buffer_width=gltexture->tex_width;
gltexture->buffer_height=gltexture->tex_height;
#ifdef USE_GLU_IMAGESCALE
gltexture->width=MIN(gltexture->realtexwidth, gltexture->tex_width);
gltexture->height=MIN(gltexture->realtexheight, gltexture->tex_height);
gltexture->buffer_width=MAX(gltexture->realtexwidth, gltexture->tex_width);
gltexture->buffer_height=MAX(gltexture->realtexheight, gltexture->tex_height);
#endif
gltexture->buffer_size=gltexture->buffer_width*gltexture->buffer_height*4;
R_UnlockPatchNum(lump);
if (gltexture->realtexwidth>gltexture->buffer_width)
return gltexture;
if (gltexture->realtexheight>gltexture->buffer_height)
return gltexture;
gltexture->textype=GLDT_PATCH;
}
return gltexture;
}
void gld_BindPatch(GLTexture *gltexture, int cm)
{
const rpatch_t *patch;
int i;
unsigned char *buffer;
if ((gltexture==last_gltexture) && (cm==last_cm))
return;
last_gltexture=gltexture;
last_cm=cm;
if (!gltexture)
return;
if (gltexture->textype!=GLDT_PATCH)
{
glBindTexture(GL_TEXTURE_2D, 0);
last_gltexture = NULL;
last_cm = -1;
return;
}
if (gltexture->glTexID[cm]!=0)
{
glBindTexture(GL_TEXTURE_2D, gltexture->glTexID[cm]);
#ifndef GL_VERSION_ES_CM_1_0
glGetTexParameteriv(GL_TEXTURE_2D,GL_TEXTURE_RESIDENT,&i);
#ifdef _DEBUG
if (i!=GL_TRUE)
lprintf(LO_INFO, "glGetTexParam: %i\n", i);
#endif
if (i==GL_TRUE)
return;
#endif
}
patch=R_CachePatchNum(gltexture->index);
buffer=(unsigned char*)Z_Malloc(gltexture->buffer_size,PU_STATIC,0);
if (gl_paletted_texture)
memset(buffer,transparent_pal_index,gltexture->buffer_size);
else
memset(buffer,0,gltexture->buffer_size);
gld_AddPatchToTexture(gltexture, buffer, patch, 0, 0, cm, gl_paletted_texture);
if (gltexture->glTexID[cm]==0)
glGenTextures(1,&gltexture->glTexID[cm]);
glBindTexture(GL_TEXTURE_2D, gltexture->glTexID[cm]);
#ifdef USE_GLU_IMAGESCALE
if ((gltexture->buffer_width>gltexture->tex_width) ||
(gltexture->buffer_height>gltexture->tex_height)
)
{
unsigned char *scaledbuffer;
scaledbuffer=(unsigned char*)Z_Malloc(gltexture->tex_width*gltexture->tex_height*4,PU_STATIC,0);
if (scaledbuffer)
{
gluScaleImage(GL_RGBA,
gltexture->buffer_width, gltexture->buffer_height,
GL_UNSIGNED_BYTE,buffer,
gltexture->tex_width, gltexture->tex_height,
GL_UNSIGNED_BYTE,scaledbuffer);
Z_Free(buffer);
buffer=scaledbuffer;
glTexImage2D( GL_TEXTURE_2D, 0, gl_tex_format,
gltexture->tex_width, gltexture->tex_height,
0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
}
}
else
#endif /* USE_GLU_IMAGESCALE */
{
if (gl_paletted_texture) {
gld_SetTexturePalette(GL_TEXTURE_2D);
#ifndef GL_VERSION_ES_CM_1_0
glTexImage2D( GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT,
gltexture->buffer_width, gltexture->buffer_height,
0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, buffer);
#endif
} else {
glTexImage2D( GL_TEXTURE_2D, 0, gl_tex_format,
gltexture->buffer_width, gltexture->buffer_height,
0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
}
}
#ifndef GL_VERSION_ES_CM_1_0
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
#else
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
#endif
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_tex_filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_tex_filter);
Z_Free(buffer);
R_UnlockPatchNum(gltexture->index);
}
GLTexture *gld_RegisterFlat(int lump, boolean mipmap)
{
GLTexture *gltexture;
gltexture=gld_AddNewGLPatchTexture(firstflat+lump);
if (!gltexture)
return NULL;
if (gltexture->textype==GLDT_UNREGISTERED)
{
gltexture->textype=GLDT_BROKEN;
gltexture->index=firstflat+lump;
gltexture->mipmap=mipmap;
gltexture->realtexwidth=64;
gltexture->realtexheight=64;
gltexture->leftoffset=0;
gltexture->topoffset=0;
gltexture->tex_width=gld_GetTexDimension(gltexture->realtexwidth);
gltexture->tex_height=gld_GetTexDimension(gltexture->realtexheight);
gltexture->width=MIN(gltexture->realtexwidth, gltexture->tex_width);
gltexture->height=MIN(gltexture->realtexheight, gltexture->tex_height);
gltexture->buffer_width=gltexture->tex_width;
gltexture->buffer_height=gltexture->tex_height;
#ifdef USE_GLU_IMAGESCALE
gltexture->width=gltexture->tex_width;
gltexture->height=gltexture->tex_height;
gltexture->buffer_width=gltexture->realtexwidth;
gltexture->buffer_height=gltexture->realtexheight;
#endif
if (gltexture->mipmap & use_mipmapping)
{
gltexture->width=gltexture->tex_width;
gltexture->height=gltexture->tex_height;
gltexture->buffer_width=gltexture->realtexwidth;
gltexture->buffer_height=gltexture->realtexheight;
}
gltexture->buffer_size=gltexture->buffer_width*gltexture->buffer_height*4;
if (gltexture->realtexwidth>gltexture->buffer_width)
return gltexture;
if (gltexture->realtexheight>gltexture->buffer_height)
return gltexture;
gltexture->textype=GLDT_FLAT;
}
return gltexture;
}
void gld_BindFlat(GLTexture *gltexture)
{
const unsigned char *flat;
int i;
unsigned char *buffer;
if (gltexture==last_gltexture)
return;
last_gltexture=gltexture;
if (!gltexture)
return;
if (gltexture->textype!=GLDT_FLAT)
{
glBindTexture(GL_TEXTURE_2D, 0);
last_gltexture = NULL;
last_cm = -1;
return;
}
if (gltexture->glTexID[CR_DEFAULT]!=0)
{
glBindTexture(GL_TEXTURE_2D, gltexture->glTexID[CR_DEFAULT]);
#ifndef GL_VERSION_ES_CM_1_0
glGetTexParameteriv(GL_TEXTURE_2D,GL_TEXTURE_RESIDENT,&i);
#ifdef _DEBUG
if (i!=GL_TRUE)
lprintf(LO_INFO, "glGetTexParam: %i\n", i);
#endif
if (i==GL_TRUE)
return;
#endif
}
flat=W_CacheLumpNum(gltexture->index);
buffer=(unsigned char*)Z_Malloc(gltexture->buffer_size,PU_STATIC,0);
if (!(gltexture->mipmap & use_mipmapping) & gl_paletted_texture)
memset(buffer,transparent_pal_index,gltexture->buffer_size);
else
memset(buffer,0,gltexture->buffer_size);
gld_AddFlatToTexture(gltexture, buffer, flat, !(gltexture->mipmap & use_mipmapping) & gl_paletted_texture);
if (gltexture->glTexID[CR_DEFAULT]==0)
glGenTextures(1,&gltexture->glTexID[CR_DEFAULT]);
glBindTexture(GL_TEXTURE_2D, gltexture->glTexID[CR_DEFAULT]);
#ifdef USE_GLU_MIPMAP
if (gltexture->mipmap & use_mipmapping)
{
gluBuild2DMipmaps(GL_TEXTURE_2D, gl_tex_format,
gltexture->buffer_width, gltexture->buffer_height,
GL_RGBA, GL_UNSIGNED_BYTE, buffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_tex_filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_mipmap_filter);
if (gl_texture_filter_anisotropic)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2.0);
}
else
#endif /* USE_GLU_MIPMAP */
{
#ifdef USE_GLU_IMAGESCALE
if ((gltexture->buffer_width!=gltexture->tex_width) ||
(gltexture->buffer_height!=gltexture->tex_height)
)
{
unsigned char *scaledbuffer;
scaledbuffer=(unsigned char*)Z_Malloc(gltexture->tex_width*gltexture->tex_height*4,PU_STATIC,0);
if (scaledbuffer)
{
gluScaleImage(GL_RGBA,
gltexture->buffer_width, gltexture->buffer_height,
GL_UNSIGNED_BYTE,buffer,
gltexture->tex_width, gltexture->tex_height,
GL_UNSIGNED_BYTE,scaledbuffer);
Z_Free(buffer);
buffer=scaledbuffer;
glTexImage2D( GL_TEXTURE_2D, 0, gl_tex_format,
gltexture->tex_width, gltexture->tex_height,
0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
}
}
else
#endif /* USE_GLU_IMAGESCALE */
{
if (gl_paletted_texture) {
gld_SetTexturePalette(GL_TEXTURE_2D);
#ifndef GL_VERSION_ES_CM_1_0
glTexImage2D( GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT,
gltexture->buffer_width, gltexture->buffer_height,
0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, buffer);
#endif
} else {
glTexImage2D( GL_TEXTURE_2D, 0, gl_tex_format,
gltexture->buffer_width, gltexture->buffer_height,
0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
}
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_tex_filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_tex_filter);
}
Z_Free(buffer);
W_UnlockLumpNum(gltexture->index);
}
static void gld_CleanTextures(void)
{
int i,j;
if (!gld_GLTextures)
return;
for (i=0; i<numtextures; i++)
{
if (gld_GLTextures[i])
{
for (j=0; j<(CR_LIMIT+MAXPLAYERS); j++)
glDeleteTextures(1,&(gld_GLTextures[i]->glTexID[j]));
Z_Free(gld_GLTextures[i]);
}
}
memset(gld_GLTextures,0,numtextures*sizeof(GLTexture *));
}
static void gld_CleanPatchTextures(void)
{
int i,j;
if (!gld_GLPatchTextures)
return;
for (i=0; i<numlumps; i++)
{
if (gld_GLPatchTextures[i])
{
for (j=0; j<(CR_LIMIT+MAXPLAYERS); j++)
glDeleteTextures(1,&(gld_GLPatchTextures[i]->glTexID[j]));
Z_Free(gld_GLPatchTextures[i]);
}
}
memset(gld_GLPatchTextures,0,numlumps*sizeof(GLTexture *));
}
void gld_Precache(void)
{
register int i;
register byte *hitlist;
if (demoplayback)
return;
{
size_t size = numflats > numsprites ? numflats : numsprites;
hitlist = Z_Malloc((size_t)numtextures > size ? numtextures : size,PU_LEVEL,0);
}
// Precache flats.
memset(hitlist, 0, numflats);
for (i = numsectors; --i >= 0; )
hitlist[sectors[i].floorpic] = hitlist[sectors[i].ceilingpic] = 1;
for (i = numflats; --i >= 0; )
if (hitlist[i])
gld_BindFlat(gld_RegisterFlat(i,true));
// Precache textures.
memset(hitlist, 0, numtextures);
for (i = numsides; --i >= 0;)
hitlist[sides[i].bottomtexture] =
hitlist[sides[i].toptexture] =
hitlist[sides[i].midtexture] = 1;
// Sky texture is always present.
// Note that F_SKY1 is the name used to
// indicate a sky floor/ceiling as a flat,
// while the sky texture is stored like
// a wall texture, with an episode dependend
// name.
hitlist[skytexture] = 0;
for (i = numtextures; --i >= 0; )
if (hitlist[i])
gld_BindTexture(gld_RegisterTexture(i,true,false));
// Precache sprites.
memset(hitlist, 0, numsprites);
{
thinker_t *th;
for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
if (th->function == P_MobjThinker)
hitlist[((mobj_t *)th)->sprite] = 1;
}
for (i=numsprites; --i >= 0;)
if (hitlist[i])
{
int j = sprites[i].numframes;
while (--j >= 0)
{
short *sflump = sprites[i].spriteframes[j].lump;
int k = 7;
do
gld_BindPatch(gld_RegisterPatch(firstspritelump + sflump[k],CR_DEFAULT),CR_DEFAULT);
while (--k >= 0);
}
}
Z_Free(hitlist);
}
void gld_CleanMemory(void)
{
gld_CleanTextures();
gld_CleanPatchTextures();
}