2009-03-05 09:07:55 +00:00
/*
2010-10-20 09:02:21 +00:00
* Copyright ( C ) 1997 - 2001 Id Software , Inc .
*
2010-10-21 07:51:49 +00:00
* 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 .
2010-10-20 09:02:21 +00:00
*
2010-10-21 07:51:49 +00:00
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of
2010-10-20 09:02:21 +00:00
* 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
2010-10-21 07:51:49 +00:00
* Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA
* 02111 - 1307 , USA .
2010-10-20 09:02:21 +00:00
*
2010-10-21 07:51:49 +00:00
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*
* Texture handling
*
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2010-10-20 09:02:21 +00:00
*/
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
# include "header/local.h"
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
image_t gltextures [ MAX_GLTEXTURES ] ;
int numgltextures ;
int base_textureid ; /* gltextures[i] = base_textureid+i */
2010-10-21 07:29:20 +00:00
extern qboolean scrap_dirty ;
extern byte scrap_texels [ MAX_SCRAPS ] [ BLOCK_WIDTH * BLOCK_HEIGHT ] ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
static byte intensitytable [ 256 ] ;
static unsigned char gammatable [ 256 ] ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
cvar_t * intensity ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
unsigned d_8to24table [ 256 ] ;
2009-03-05 09:07:55 +00:00
2010-10-22 09:12:38 +00:00
qboolean R_Upload8 ( byte * data , int width , int height , qboolean mipmap , qboolean is_sky ) ;
qboolean R_Upload32 ( unsigned * data , int width , int height , qboolean mipmap ) ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
int gl_solid_format = 3 ;
int gl_alpha_format = 4 ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
int gl_tex_solid_format = 3 ;
int gl_tex_alpha_format = 4 ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
int gl_filter_min = GL_LINEAR_MIPMAP_NEAREST ;
int gl_filter_max = GL_LINEAR ;
2009-03-05 09:07:55 +00:00
2010-10-22 09:12:38 +00:00
int Draw_GetPalette ( void ) ;
2010-10-21 07:51:49 +00:00
2010-10-20 09:02:21 +00:00
typedef struct
{
char * name ;
int minimize , maximize ;
} glmode_t ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
glmode_t modes [ ] = {
{ " GL_NEAREST " , GL_NEAREST , GL_NEAREST } ,
{ " GL_LINEAR " , GL_LINEAR , GL_LINEAR } ,
{ " GL_NEAREST_MIPMAP_NEAREST " , GL_NEAREST_MIPMAP_NEAREST , GL_NEAREST } ,
{ " GL_LINEAR_MIPMAP_NEAREST " , GL_LINEAR_MIPMAP_NEAREST , GL_LINEAR } ,
{ " GL_NEAREST_MIPMAP_LINEAR " , GL_NEAREST_MIPMAP_LINEAR , GL_NEAREST } ,
{ " GL_LINEAR_MIPMAP_LINEAR " , GL_LINEAR_MIPMAP_LINEAR , GL_LINEAR }
} ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
# define NUM_GL_MODES ( sizeof ( modes ) / sizeof ( glmode_t ) )
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
typedef struct
{
char * name ;
int mode ;
} gltmode_t ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
gltmode_t gl_alpha_modes [ ] = {
{ " default " , 4 } ,
{ " GL_RGBA " , GL_RGBA } ,
{ " GL_RGBA8 " , GL_RGBA8 } ,
{ " GL_RGB5_A1 " , GL_RGB5_A1 } ,
{ " GL_RGBA4 " , GL_RGBA4 } ,
{ " GL_RGBA2 " , GL_RGBA2 } ,
} ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
# define NUM_GL_ALPHA_MODES ( sizeof ( gl_alpha_modes ) / sizeof ( gltmode_t ) )
gltmode_t gl_solid_modes [ ] = {
{ " default " , 3 } ,
{ " GL_RGB " , GL_RGB } ,
{ " GL_RGB8 " , GL_RGB8 } ,
{ " GL_RGB5 " , GL_RGB5 } ,
{ " GL_RGB4 " , GL_RGB4 } ,
{ " GL_R3_G3_B2 " , GL_R3_G3_B2 } ,
2012-06-04 09:46:08 +00:00
# ifdef GL_RGB2_EXT
2010-10-20 09:02:21 +00:00
{ " GL_RGB2 " , GL_RGB2_EXT } ,
2012-06-04 09:46:08 +00:00
# endif
2010-10-20 09:02:21 +00:00
} ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
# define NUM_GL_SOLID_MODES ( sizeof ( gl_solid_modes ) / sizeof ( gltmode_t ) )
2010-10-21 07:51:49 +00:00
typedef struct
{
short x , y ;
} floodfill_t ;
/* must be a power of 2 */
# define FLOODFILL_FIFO_SIZE 0x1000
# define FLOODFILL_FIFO_MASK ( FLOODFILL_FIFO_SIZE - 1 )
# define FLOODFILL_STEP( off, dx, dy ) \
{ \
if ( pos [ off ] = = fillcolor ) \
{ \
pos [ off ] = 255 ; \
fifo [ inpt ] . x = x + ( dx ) , fifo [ inpt ] . y = y + ( dy ) ; \
inpt = ( inpt + 1 ) & FLOODFILL_FIFO_MASK ; \
} \
else if ( pos [ off ] ! = 255 ) \
{ \
fdc = pos [ off ] ; \
} \
}
int upload_width , upload_height ;
qboolean uploaded_paletted ;
2010-10-25 12:55:59 +00:00
void
R_SetTexturePalette ( unsigned palette [ 256 ] )
{
int i ;
unsigned char temptable [ 768 ] ;
if ( qglColorTableEXT & & gl_ext_palettedtexture - > value )
{
for ( i = 0 ; i < 256 ; i + + )
{
temptable [ i * 3 + 0 ] = ( palette [ i ] > > 0 ) & 0xff ;
temptable [ i * 3 + 1 ] = ( palette [ i ] > > 8 ) & 0xff ;
temptable [ i * 3 + 2 ] = ( palette [ i ] > > 16 ) & 0xff ;
}
qglColorTableEXT ( GL_SHARED_TEXTURE_PALETTE_EXT ,
GL_RGB ,
256 ,
GL_RGB ,
GL_UNSIGNED_BYTE ,
temptable ) ;
}
}
2010-10-25 12:33:55 +00:00
void
R_EnableMultitexture ( qboolean enable )
{
if ( ! qglSelectTextureSGIS & & ! qglActiveTextureARB )
{
return ;
}
if ( enable )
{
R_SelectTexture ( QGL_TEXTURE1 ) ;
qglEnable ( GL_TEXTURE_2D ) ;
R_TexEnv ( GL_REPLACE ) ;
}
else
{
R_SelectTexture ( QGL_TEXTURE1 ) ;
qglDisable ( GL_TEXTURE_2D ) ;
R_TexEnv ( GL_REPLACE ) ;
}
R_SelectTexture ( QGL_TEXTURE0 ) ;
R_TexEnv ( GL_REPLACE ) ;
}
void
R_SelectTexture ( GLenum texture )
{
int tmu ;
if ( ! qglSelectTextureSGIS & & ! qglActiveTextureARB )
{
return ;
}
if ( texture = = QGL_TEXTURE0 )
{
tmu = 0 ;
}
else
{
tmu = 1 ;
}
if ( tmu = = gl_state . currenttmu )
{
return ;
}
gl_state . currenttmu = tmu ;
if ( qglSelectTextureSGIS )
{
qglSelectTextureSGIS ( texture ) ;
}
else if ( qglActiveTextureARB )
{
qglActiveTextureARB ( texture ) ;
qglClientActiveTextureARB ( texture ) ;
}
}
2010-10-20 09:02:21 +00:00
void
2010-10-22 09:12:38 +00:00
R_TexEnv ( GLenum mode )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
static int lastmodes [ 2 ] = { - 1 , - 1 } ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
if ( mode ! = lastmodes [ gl_state . currenttmu ] )
2009-03-05 09:07:55 +00:00
{
qglTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , mode ) ;
2010-10-20 09:02:21 +00:00
lastmodes [ gl_state . currenttmu ] = mode ;
2009-03-05 09:07:55 +00:00
}
}
2010-10-20 09:02:21 +00:00
void
2010-10-22 09:12:38 +00:00
R_Bind ( int texnum )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
extern image_t * draw_chars ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
if ( gl_nobind - > value & & draw_chars ) /* performance evaluation option */
{
2009-03-05 09:07:55 +00:00
texnum = draw_chars - > texnum ;
2010-10-20 09:02:21 +00:00
}
if ( gl_state . currenttextures [ gl_state . currenttmu ] = = texnum )
{
2009-03-05 09:07:55 +00:00
return ;
2010-10-20 09:02:21 +00:00
}
gl_state . currenttextures [ gl_state . currenttmu ] = texnum ;
qglBindTexture ( GL_TEXTURE_2D , texnum ) ;
2009-03-05 09:07:55 +00:00
}
2010-10-20 09:02:21 +00:00
void
2010-10-22 09:12:38 +00:00
R_MBind ( GLenum target , int texnum )
2009-03-05 09:07:55 +00:00
{
2010-10-25 12:33:55 +00:00
R_SelectTexture ( target ) ;
2009-03-05 09:07:55 +00:00
if ( target = = QGL_TEXTURE0 )
{
2010-10-20 09:02:21 +00:00
if ( gl_state . currenttextures [ 0 ] = = texnum )
{
2009-03-05 09:07:55 +00:00
return ;
2010-10-20 09:02:21 +00:00
}
2009-03-05 09:07:55 +00:00
}
else
{
2010-10-20 09:02:21 +00:00
if ( gl_state . currenttextures [ 1 ] = = texnum )
{
2009-03-05 09:07:55 +00:00
return ;
2010-10-20 09:02:21 +00:00
}
2009-03-05 09:07:55 +00:00
}
2010-10-20 09:02:21 +00:00
2010-10-22 09:12:38 +00:00
R_Bind ( texnum ) ;
2009-03-05 09:07:55 +00:00
}
2010-10-25 12:33:55 +00:00
2010-10-20 09:02:21 +00:00
void
2010-10-22 09:12:38 +00:00
R_TextureMode ( char * string )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
int i ;
image_t * glt ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
for ( i = 0 ; i < NUM_GL_MODES ; i + + )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
if ( ! Q_stricmp ( modes [ i ] . name , string ) )
{
2009-03-05 09:07:55 +00:00
break ;
2010-10-20 09:02:21 +00:00
}
2009-03-05 09:07:55 +00:00
}
2010-10-20 09:02:21 +00:00
if ( i = = NUM_GL_MODES )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
ri . Con_Printf ( PRINT_ALL , " bad filter name \n " ) ;
2009-03-05 09:07:55 +00:00
return ;
}
2010-10-20 09:02:21 +00:00
gl_filter_min = modes [ i ] . minimize ;
gl_filter_max = modes [ i ] . maximize ;
2009-03-05 09:07:55 +00:00
2011-10-17 10:43:48 +00:00
/* clamp selected anisotropy */
if ( gl_config . anisotropic )
{
if ( gl_anisotropic - > value > gl_config . max_anisotropy )
{
ri . Cvar_SetValue ( " gl_anisotropic " , gl_config . max_anisotropy ) ;
}
else if ( gl_anisotropic - > value < 1.0 )
{
ri . Cvar_SetValue ( " gl_anisotropic " , 1.0 ) ;
}
}
2010-10-20 09:02:21 +00:00
/* change all the existing mipmap texture objects */
for ( i = 0 , glt = gltextures ; i < numgltextures ; i + + , glt + + )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
if ( ( glt - > type ! = it_pic ) & & ( glt - > type ! = it_sky ) )
2009-03-05 09:07:55 +00:00
{
2010-10-22 09:12:38 +00:00
R_Bind ( glt - > texnum ) ;
2010-10-20 09:02:21 +00:00
qglTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , gl_filter_min ) ;
qglTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , gl_filter_max ) ;
2011-10-17 10:43:48 +00:00
/* Set anisotropic filter if supported and enabled */
if ( gl_config . anisotropic & & gl_anisotropic - > value )
{
qglTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MAX_ANISOTROPY_EXT , gl_anisotropic - > value ) ;
}
2009-03-05 09:07:55 +00:00
}
}
}
2010-10-20 09:02:21 +00:00
void
2010-10-22 09:12:38 +00:00
R_TextureAlphaMode ( char * string )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
int i ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
for ( i = 0 ; i < NUM_GL_ALPHA_MODES ; i + + )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
if ( ! Q_stricmp ( gl_alpha_modes [ i ] . name , string ) )
{
2009-03-05 09:07:55 +00:00
break ;
2010-10-20 09:02:21 +00:00
}
2009-03-05 09:07:55 +00:00
}
2010-10-20 09:02:21 +00:00
if ( i = = NUM_GL_ALPHA_MODES )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
ri . Con_Printf ( PRINT_ALL , " bad alpha texture mode name \n " ) ;
2009-03-05 09:07:55 +00:00
return ;
}
2010-10-20 09:02:21 +00:00
gl_tex_alpha_format = gl_alpha_modes [ i ] . mode ;
2009-03-05 09:07:55 +00:00
}
2010-10-20 09:02:21 +00:00
void
2010-10-22 09:12:38 +00:00
R_TextureSolidMode ( char * string )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
int i ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
for ( i = 0 ; i < NUM_GL_SOLID_MODES ; i + + )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
if ( ! Q_stricmp ( gl_solid_modes [ i ] . name , string ) )
{
2009-03-05 09:07:55 +00:00
break ;
2010-10-20 09:02:21 +00:00
}
2009-03-05 09:07:55 +00:00
}
2010-10-20 09:02:21 +00:00
if ( i = = NUM_GL_SOLID_MODES )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
ri . Con_Printf ( PRINT_ALL , " bad solid texture mode name \n " ) ;
2009-03-05 09:07:55 +00:00
return ;
}
2010-10-20 09:02:21 +00:00
gl_tex_solid_format = gl_solid_modes [ i ] . mode ;
2009-03-05 09:07:55 +00:00
}
2010-10-20 09:02:21 +00:00
void
2010-10-22 09:12:38 +00:00
R_ImageList_f ( void )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
int i ;
image_t * image ;
int texels ;
const char * palstrings [ 2 ] = {
2009-03-05 09:07:55 +00:00
" RGB " ,
" PAL "
} ;
2010-10-20 09:02:21 +00:00
ri . Con_Printf ( PRINT_ALL , " ------------------ \n " ) ;
2009-03-05 09:07:55 +00:00
texels = 0 ;
2010-10-20 09:02:21 +00:00
for ( i = 0 , image = gltextures ; i < numgltextures ; i + + , image + + )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
if ( image - > texnum < = 0 )
{
2009-03-05 09:07:55 +00:00
continue ;
2010-10-20 09:02:21 +00:00
}
texels + = image - > upload_width * image - > upload_height ;
switch ( image - > type )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
case it_skin :
ri . Con_Printf ( PRINT_ALL , " M " ) ;
break ;
case it_sprite :
ri . Con_Printf ( PRINT_ALL , " S " ) ;
break ;
case it_wall :
ri . Con_Printf ( PRINT_ALL , " W " ) ;
break ;
case it_pic :
ri . Con_Printf ( PRINT_ALL , " P " ) ;
break ;
default :
ri . Con_Printf ( PRINT_ALL , " " ) ;
break ;
2009-03-05 09:07:55 +00:00
}
2010-10-20 09:02:21 +00:00
ri . Con_Printf ( PRINT_ALL , " %3i %3i %s: %s \n " ,
image - > upload_width , image - > upload_height , palstrings [ image - > paletted ] , image - > name ) ;
2009-03-05 09:07:55 +00:00
}
2010-10-20 09:02:21 +00:00
ri . Con_Printf ( PRINT_ALL , " Total texel count (not counting mipmaps): %i \n " , texels ) ;
}
2009-03-05 09:07:55 +00:00
/*
2010-10-20 09:02:21 +00:00
* Fill background pixels so mipmapping doesn ' t have haloes
*/
void
R_FloodFillSkin ( byte * skin , int skinwidth , int skinheight )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
byte fillcolor = * skin ; /* assume this is the pixel to fill */
floodfill_t fifo [ FLOODFILL_FIFO_SIZE ] ;
int inpt = 0 , outpt = 0 ;
int filledcolor = - 1 ;
int i ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
if ( filledcolor = = - 1 )
2009-03-05 09:07:55 +00:00
{
filledcolor = 0 ;
2010-10-20 09:02:21 +00:00
/* attempt to find opaque black */
for ( i = 0 ; i < 256 ; + + i )
{
if ( LittleLong ( d_8to24table [ i ] ) = = ( 255 < < 0 ) ) /* alpha 1.0 */
2009-03-05 09:07:55 +00:00
{
filledcolor = i ;
break ;
}
2010-10-20 09:02:21 +00:00
}
2009-03-05 09:07:55 +00:00
}
2010-10-20 09:02:21 +00:00
/* can't fill to filled color or to transparent color (used as visited marker) */
if ( ( fillcolor = = filledcolor ) | | ( fillcolor = = 255 ) )
2009-03-05 09:07:55 +00:00
{
return ;
}
2010-10-20 09:02:21 +00:00
fifo [ inpt ] . x = 0 , fifo [ inpt ] . y = 0 ;
inpt = ( inpt + 1 ) & FLOODFILL_FIFO_MASK ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
while ( outpt ! = inpt )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
int x = fifo [ outpt ] . x , y = fifo [ outpt ] . y ;
int fdc = filledcolor ;
byte * pos = & skin [ x + skinwidth * y ] ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
outpt = ( outpt + 1 ) & FLOODFILL_FIFO_MASK ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
if ( x > 0 )
{
FLOODFILL_STEP ( - 1 , - 1 , 0 ) ;
}
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
if ( x < skinwidth - 1 )
{
FLOODFILL_STEP ( 1 , 1 , 0 ) ;
}
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
if ( y > 0 )
{
FLOODFILL_STEP ( - skinwidth , 0 , - 1 ) ;
}
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
if ( y < skinheight - 1 )
{
FLOODFILL_STEP ( skinwidth , 0 , 1 ) ;
}
skin [ x + skinwidth * y ] = fdc ;
}
}
void
2010-10-22 09:12:38 +00:00
R_ResampleTexture ( unsigned * in , int inwidth , int inheight , unsigned * out , int outwidth , int outheight )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
int i , j ;
unsigned * inrow , * inrow2 ;
unsigned frac , fracstep ;
unsigned p1 [ 1024 ] , p2 [ 1024 ] ;
byte * pix1 , * pix2 , * pix3 , * pix4 ;
fracstep = inwidth * 0x10000 / outwidth ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
frac = fracstep > > 2 ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
for ( i = 0 ; i < outwidth ; i + + )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
p1 [ i ] = 4 * ( frac > > 16 ) ;
2009-03-05 09:07:55 +00:00
frac + = fracstep ;
}
2010-10-20 09:02:21 +00:00
frac = 3 * ( fracstep > > 2 ) ;
for ( i = 0 ; i < outwidth ; i + + )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
p2 [ i ] = 4 * ( frac > > 16 ) ;
2009-03-05 09:07:55 +00:00
frac + = fracstep ;
}
2010-10-20 09:02:21 +00:00
for ( i = 0 ; i < outheight ; i + + , out + = outwidth )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
inrow = in + inwidth * ( int ) ( ( i + 0.25 ) * inheight / outheight ) ;
inrow2 = in + inwidth * ( int ) ( ( i + 0.75 ) * inheight / outheight ) ;
for ( j = 0 ; j < outwidth ; j + + )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
pix1 = ( byte * ) inrow + p1 [ j ] ;
pix2 = ( byte * ) inrow + p2 [ j ] ;
pix3 = ( byte * ) inrow2 + p1 [ j ] ;
pix4 = ( byte * ) inrow2 + p2 [ j ] ;
( ( byte * ) ( out + j ) ) [ 0 ] = ( pix1 [ 0 ] + pix2 [ 0 ] + pix3 [ 0 ] + pix4 [ 0 ] ) > > 2 ;
( ( byte * ) ( out + j ) ) [ 1 ] = ( pix1 [ 1 ] + pix2 [ 1 ] + pix3 [ 1 ] + pix4 [ 1 ] ) > > 2 ;
( ( byte * ) ( out + j ) ) [ 2 ] = ( pix1 [ 2 ] + pix2 [ 2 ] + pix3 [ 2 ] + pix4 [ 2 ] ) > > 2 ;
( ( byte * ) ( out + j ) ) [ 3 ] = ( pix1 [ 3 ] + pix2 [ 3 ] + pix3 [ 3 ] + pix4 [ 3 ] ) > > 2 ;
2009-03-05 09:07:55 +00:00
}
}
}
/*
2010-10-20 09:02:21 +00:00
* Scale up the pixel values in a
* texture to increase the
* lighting range
*/
void
2010-10-22 09:12:38 +00:00
R_LightScaleTexture ( unsigned * in , int inwidth , int inheight , qboolean only_gamma )
2009-03-05 09:07:55 +00:00
{
if ( only_gamma )
{
2010-10-20 09:02:21 +00:00
int i , c ;
byte * p ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
p = ( byte * ) in ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
c = inwidth * inheight ;
for ( i = 0 ; i < c ; i + + , p + = 4 )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
p [ 0 ] = gammatable [ p [ 0 ] ] ;
p [ 1 ] = gammatable [ p [ 1 ] ] ;
p [ 2 ] = gammatable [ p [ 2 ] ] ;
2009-03-05 09:07:55 +00:00
}
}
else
{
2010-10-20 09:02:21 +00:00
int i , c ;
byte * p ;
p = ( byte * ) in ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
c = inwidth * inheight ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
for ( i = 0 ; i < c ; i + + , p + = 4 )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
p [ 0 ] = gammatable [ intensitytable [ p [ 0 ] ] ] ;
p [ 1 ] = gammatable [ intensitytable [ p [ 1 ] ] ] ;
p [ 2 ] = gammatable [ intensitytable [ p [ 2 ] ] ] ;
2009-03-05 09:07:55 +00:00
}
}
}
/*
2010-10-20 09:02:21 +00:00
* Operates in place , quartering the size of the texture
*/
void
2010-10-22 09:12:38 +00:00
R_MipMap ( byte * in , int width , int height )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
int i , j ;
byte * out ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
width < < = 2 ;
2009-03-05 09:07:55 +00:00
height > > = 1 ;
out = in ;
2010-10-20 09:02:21 +00:00
for ( i = 0 ; i < height ; i + + , in + = width )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
for ( j = 0 ; j < width ; j + = 8 , out + = 4 , in + = 8 )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
out [ 0 ] = ( in [ 0 ] + in [ 4 ] + in [ width + 0 ] + in [ width + 4 ] ) > > 2 ;
out [ 1 ] = ( in [ 1 ] + in [ 5 ] + in [ width + 1 ] + in [ width + 5 ] ) > > 2 ;
out [ 2 ] = ( in [ 2 ] + in [ 6 ] + in [ width + 2 ] + in [ width + 6 ] ) > > 2 ;
out [ 3 ] = ( in [ 3 ] + in [ 7 ] + in [ width + 3 ] + in [ width + 7 ] ) > > 2 ;
2009-03-05 09:07:55 +00:00
}
}
}
/*
2010-10-20 09:02:21 +00:00
* Returns has_alpha
*/
void
2010-10-22 09:12:38 +00:00
R_BuildPalettedTexture ( unsigned char * paletted_texture , unsigned char * scaled , int scaled_width , int scaled_height )
2009-03-05 09:07:55 +00:00
{
int i ;
for ( i = 0 ; i < scaled_width * scaled_height ; i + + )
{
unsigned int r , g , b , c ;
2010-10-20 09:02:21 +00:00
r = ( scaled [ 0 ] > > 3 ) & 31 ;
g = ( scaled [ 1 ] > > 2 ) & 63 ;
b = ( scaled [ 2 ] > > 3 ) & 31 ;
2009-03-05 09:07:55 +00:00
c = r | ( g < < 5 ) | ( b < < 11 ) ;
2010-10-20 09:02:21 +00:00
paletted_texture [ i ] = gl_state . d_16to8table [ c ] ;
2009-03-05 09:07:55 +00:00
scaled + = 4 ;
}
}
2010-10-20 09:02:21 +00:00
qboolean
2010-10-22 09:12:38 +00:00
R_Upload32 ( unsigned * data , int width , int height , qboolean mipmap )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
int samples ;
unsigned scaled [ 256 * 256 ] ;
2010-10-25 12:55:59 +00:00
unsigned char paletted_texture [ 256 * 256 ] ;
2010-10-20 09:02:21 +00:00
int scaled_width , scaled_height ;
int i , c ;
byte * scan ;
2009-03-05 09:07:55 +00:00
int comp ;
uploaded_paletted = false ;
2010-10-20 09:02:21 +00:00
for ( scaled_width = 1 ; scaled_width < width ; scaled_width < < = 1 )
{
}
if ( gl_round_down - > value & & ( scaled_width > width ) & & mipmap )
{
2009-03-05 09:07:55 +00:00
scaled_width > > = 1 ;
2010-10-20 09:02:21 +00:00
}
for ( scaled_height = 1 ; scaled_height < height ; scaled_height < < = 1 )
{
}
if ( gl_round_down - > value & & ( scaled_height > height ) & & mipmap )
{
2009-03-05 09:07:55 +00:00
scaled_height > > = 1 ;
2010-10-20 09:02:21 +00:00
}
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
/* let people sample down the world textures for speed */
if ( mipmap )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
scaled_width > > = ( int ) gl_picmip - > value ;
scaled_height > > = ( int ) gl_picmip - > value ;
2009-03-05 09:07:55 +00:00
}
2010-10-20 09:02:21 +00:00
/* don't ever bother with >256 textures */
if ( scaled_width > 256 )
{
2009-03-05 09:07:55 +00:00
scaled_width = 256 ;
2010-10-20 09:02:21 +00:00
}
if ( scaled_height > 256 )
{
2009-03-05 09:07:55 +00:00
scaled_height = 256 ;
2010-10-20 09:02:21 +00:00
}
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
if ( scaled_width < 1 )
{
2009-03-05 09:07:55 +00:00
scaled_width = 1 ;
2010-10-20 09:02:21 +00:00
}
if ( scaled_height < 1 )
{
2009-03-05 09:07:55 +00:00
scaled_height = 1 ;
2010-10-20 09:02:21 +00:00
}
2009-03-05 09:07:55 +00:00
upload_width = scaled_width ;
upload_height = scaled_height ;
2010-10-20 09:02:21 +00:00
if ( scaled_width * scaled_height > sizeof ( scaled ) / 4 )
{
2010-10-22 09:12:38 +00:00
ri . Sys_Error ( ERR_DROP , " R_Upload32: too big " ) ;
2010-10-20 09:02:21 +00:00
}
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
/* scan the texture for any non-255 alpha */
c = width * height ;
scan = ( ( byte * ) data ) + 3 ;
2009-03-05 09:07:55 +00:00
samples = gl_solid_format ;
2010-10-20 09:02:21 +00:00
for ( i = 0 ; i < c ; i + + , scan + = 4 )
2009-03-05 09:07:55 +00:00
{
if ( * scan ! = 255 )
{
samples = gl_alpha_format ;
break ;
}
}
2010-10-20 09:02:21 +00:00
if ( samples = = gl_solid_format )
{
comp = gl_tex_solid_format ;
}
else if ( samples = = gl_alpha_format )
{
comp = gl_tex_alpha_format ;
}
else
{
ri . Con_Printf ( PRINT_ALL ,
" Unknown number of texture components %i \n " ,
samples ) ;
comp = samples ;
2009-03-05 09:07:55 +00:00
}
2010-10-20 09:02:21 +00:00
if ( ( scaled_width = = width ) & & ( scaled_height = = height ) )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
if ( ! mipmap )
2009-03-05 09:07:55 +00:00
{
2010-10-25 12:55:59 +00:00
if ( qglColorTableEXT & & gl_ext_palettedtexture - > value & & ( samples = = gl_solid_format ) )
{
uploaded_paletted = true ;
R_BuildPalettedTexture ( paletted_texture , ( unsigned char * ) data , scaled_width , scaled_height ) ;
2011-10-17 10:43:48 +00:00
qglTexImage2D ( GL_TEXTURE_2D , 0 , GL_COLOR_INDEX8_EXT , scaled_width ,
scaled_height , 0 , GL_COLOR_INDEX , GL_UNSIGNED_BYTE , paletted_texture ) ;
2010-10-25 12:55:59 +00:00
}
else
{
qglTexImage2D ( GL_TEXTURE_2D , 0 , comp , scaled_width , scaled_height , 0 , GL_RGBA , GL_UNSIGNED_BYTE , data ) ;
}
2009-03-05 09:07:55 +00:00
goto done ;
}
2010-10-20 09:02:21 +00:00
memcpy ( scaled , data , width * height * 4 ) ;
2009-03-05 09:07:55 +00:00
}
else
2010-10-20 09:02:21 +00:00
{
2010-10-22 09:12:38 +00:00
R_ResampleTexture ( data , width , height , scaled , scaled_width , scaled_height ) ;
2010-10-20 09:02:21 +00:00
}
2009-03-05 09:07:55 +00:00
2010-10-22 09:12:38 +00:00
R_LightScaleTexture ( scaled , scaled_width , scaled_height , ! mipmap ) ;
2010-10-25 12:55:59 +00:00
if ( qglColorTableEXT & & gl_ext_palettedtexture - > value & & ( samples = = gl_solid_format ) )
{
uploaded_paletted = true ;
R_BuildPalettedTexture ( paletted_texture , ( unsigned char * ) scaled , scaled_width , scaled_height ) ;
2011-10-17 10:43:48 +00:00
qglTexImage2D ( GL_TEXTURE_2D , 0 , GL_COLOR_INDEX8_EXT , scaled_width , scaled_height ,
0 , GL_COLOR_INDEX , GL_UNSIGNED_BYTE , paletted_texture ) ;
2010-10-25 12:55:59 +00:00
}
else
{
qglTexImage2D ( GL_TEXTURE_2D , 0 , comp , scaled_width , scaled_height , 0 , GL_RGBA , GL_UNSIGNED_BYTE , scaled ) ;
}
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
if ( mipmap )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
int miplevel ;
2009-03-05 09:07:55 +00:00
miplevel = 0 ;
2010-10-20 09:02:21 +00:00
while ( scaled_width > 1 | | scaled_height > 1 )
2009-03-05 09:07:55 +00:00
{
2010-10-22 09:12:38 +00:00
R_MipMap ( ( byte * ) scaled , scaled_width , scaled_height ) ;
2009-03-05 09:07:55 +00:00
scaled_width > > = 1 ;
scaled_height > > = 1 ;
2010-10-20 09:02:21 +00:00
if ( scaled_width < 1 )
{
2009-03-05 09:07:55 +00:00
scaled_width = 1 ;
2010-10-20 09:02:21 +00:00
}
if ( scaled_height < 1 )
{
2009-03-05 09:07:55 +00:00
scaled_height = 1 ;
2010-10-20 09:02:21 +00:00
}
2009-03-05 09:07:55 +00:00
miplevel + + ;
2010-10-25 12:55:59 +00:00
if ( qglColorTableEXT & & gl_ext_palettedtexture - > value & & ( samples = = gl_solid_format ) )
{
uploaded_paletted = true ;
R_BuildPalettedTexture ( paletted_texture , ( unsigned char * ) scaled , scaled_width , scaled_height ) ;
2011-10-17 10:43:48 +00:00
qglTexImage2D ( GL_TEXTURE_2D , miplevel , GL_COLOR_INDEX8_EXT , scaled_width , scaled_height ,
0 , GL_COLOR_INDEX , GL_UNSIGNED_BYTE , paletted_texture ) ;
2010-10-25 12:55:59 +00:00
}
else
{
qglTexImage2D ( GL_TEXTURE_2D , miplevel , comp , scaled_width , scaled_height , 0 , GL_RGBA , GL_UNSIGNED_BYTE , scaled ) ;
}
2009-03-05 09:07:55 +00:00
}
}
2010-10-21 07:51:49 +00:00
done :
2010-10-20 09:02:21 +00:00
if ( mipmap )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
qglTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , gl_filter_min ) ;
qglTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , gl_filter_max ) ;
2009-03-05 09:07:55 +00:00
}
else
{
2010-10-20 09:02:21 +00:00
qglTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , gl_filter_max ) ;
qglTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , gl_filter_max ) ;
2009-03-05 09:07:55 +00:00
}
2011-10-17 10:43:48 +00:00
if ( mipmap & & gl_config . anisotropic & & gl_anisotropic - > value )
{
qglTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MAX_ANISOTROPY_EXT , gl_anisotropic - > value ) ;
}
2010-10-20 09:02:21 +00:00
return ( samples = = gl_alpha_format ) ;
2009-03-05 09:07:55 +00:00
}
/*
2010-10-20 09:02:21 +00:00
* Returns has_alpha
*/
qboolean
2010-10-22 09:12:38 +00:00
R_Upload8 ( byte * data , int width , int height , qboolean mipmap , qboolean is_sky )
2010-10-20 09:02:21 +00:00
{
unsigned trans [ 512 * 256 ] ;
int i , s ;
int p ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
s = width * height ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
if ( s > sizeof ( trans ) / 4 )
{
2010-10-22 09:12:38 +00:00
ri . Sys_Error ( ERR_DROP , " R_Upload8: too large " ) ;
2010-10-20 09:02:21 +00:00
}
2010-10-25 12:55:59 +00:00
if ( qglColorTableEXT & & gl_ext_palettedtexture - > value & & is_sky )
2010-10-20 09:02:21 +00:00
{
2010-10-25 12:55:59 +00:00
qglTexImage2D ( GL_TEXTURE_2D ,
0 ,
GL_COLOR_INDEX8_EXT ,
width ,
height ,
0 ,
GL_COLOR_INDEX ,
GL_UNSIGNED_BYTE ,
data ) ;
qglTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , gl_filter_max ) ;
qglTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , gl_filter_max ) ;
2010-10-25 12:33:55 +00:00
2010-10-25 12:55:59 +00:00
return ( false ) ; /* SBF: FIXME - what is the correct return value? */
}
else
{
for ( i = 0 ; i < s ; i + + )
2010-10-25 12:33:55 +00:00
{
2010-10-25 12:55:59 +00:00
p = data [ i ] ;
trans [ i ] = d_8to24table [ p ] ;
/* transparent, so scan around for another color
* to avoid alpha fringes */
if ( p = = 255 )
2010-10-20 09:02:21 +00:00
{
2010-10-25 12:55:59 +00:00
if ( ( i > width ) & & ( data [ i - width ] ! = 255 ) )
{
p = data [ i - width ] ;
}
else if ( ( i < s - width ) & & ( data [ i + width ] ! = 255 ) )
{
p = data [ i + width ] ;
}
else if ( ( i > 0 ) & & ( data [ i - 1 ] ! = 255 ) )
{
p = data [ i - 1 ] ;
}
else if ( ( i < s - 1 ) & & ( data [ i + 1 ] ! = 255 ) )
{
p = data [ i + 1 ] ;
}
else
{
p = 0 ;
}
/* copy rgb components */
( ( byte * ) & trans [ i ] ) [ 0 ] = ( ( byte * ) & d_8to24table [ p ] ) [ 0 ] ;
( ( byte * ) & trans [ i ] ) [ 1 ] = ( ( byte * ) & d_8to24table [ p ] ) [ 1 ] ;
( ( byte * ) & trans [ i ] ) [ 2 ] = ( ( byte * ) & d_8to24table [ p ] ) [ 2 ] ;
2010-10-20 09:02:21 +00:00
}
2009-03-05 09:07:55 +00:00
}
2009-10-04 10:58:42 +00:00
2010-10-25 12:55:59 +00:00
return ( R_Upload32 ( trans , width , height , mipmap ) ) ;
}
2009-03-05 09:07:55 +00:00
}
/*
2010-10-20 09:02:21 +00:00
* This is also used as an entry point for the generated r_notexture
*/
image_t *
2012-03-12 08:53:22 +00:00
R_LoadPic ( char * name , byte * pic , int width , int realwidth , int height , int realheight , imagetype_t type , int bits )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
image_t * image ;
int i ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
/* find a free image_t */
for ( i = 0 , image = gltextures ; i < numgltextures ; i + + , image + + )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
if ( ! image - > texnum )
{
2009-03-05 09:07:55 +00:00
break ;
2010-10-20 09:02:21 +00:00
}
2009-03-05 09:07:55 +00:00
}
2010-10-20 09:02:21 +00:00
if ( i = = numgltextures )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
if ( numgltextures = = MAX_GLTEXTURES )
{
ri . Sys_Error ( ERR_DROP , " MAX_GLTEXTURES " ) ;
}
2009-03-05 09:07:55 +00:00
numgltextures + + ;
}
2010-10-20 09:02:21 +00:00
image = & gltextures [ i ] ;
if ( strlen ( name ) > = sizeof ( image - > name ) )
{
ri . Sys_Error ( ERR_DROP , " Draw_LoadPic: \" %s \" is too long " , name ) ;
}
strcpy ( image - > name , name ) ;
2009-03-05 09:07:55 +00:00
image - > registration_sequence = registration_sequence ;
image - > width = width ;
image - > height = height ;
image - > type = type ;
2010-10-20 09:02:21 +00:00
if ( ( type = = it_skin ) & & ( bits = = 8 ) )
{
R_FloodFillSkin ( pic , width , height ) ;
}
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
/* load little pics into the scrap */
if ( ( image - > type = = it_pic ) & & ( bits = = 8 ) & &
( image - > width < 64 ) & & ( image - > height < 64 ) )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
int x , y ;
int i , j , k ;
int texnum ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
texnum = Scrap_AllocBlock ( image - > width , image - > height , & x , & y ) ;
if ( texnum = = - 1 )
{
2009-03-05 09:07:55 +00:00
goto nonscrap ;
2010-10-20 09:02:21 +00:00
}
2009-03-05 09:07:55 +00:00
scrap_dirty = true ;
2010-10-20 09:02:21 +00:00
/* copy the texels into the scrap block */
2009-03-05 09:07:55 +00:00
k = 0 ;
2010-10-20 09:02:21 +00:00
for ( i = 0 ; i < image - > height ; i + + )
{
for ( j = 0 ; j < image - > width ; j + + , k + + )
{
scrap_texels [ texnum ] [ ( y + i ) * BLOCK_WIDTH + x + j ] = pic [ k ] ;
}
}
2009-03-05 09:07:55 +00:00
image - > texnum = TEXNUM_SCRAPS + texnum ;
image - > scrap = true ;
image - > has_alpha = true ;
2010-10-20 09:02:21 +00:00
image - > sl = ( x + 0.01 ) / ( float ) BLOCK_WIDTH ;
image - > sh = ( x + image - > width - 0.01 ) / ( float ) BLOCK_WIDTH ;
image - > tl = ( y + 0.01 ) / ( float ) BLOCK_WIDTH ;
image - > th = ( y + image - > height - 0.01 ) / ( float ) BLOCK_WIDTH ;
2009-03-05 09:07:55 +00:00
}
else
{
2010-10-20 09:02:21 +00:00
nonscrap :
2009-03-05 09:07:55 +00:00
image - > scrap = false ;
2010-10-20 09:02:21 +00:00
image - > texnum = TEXNUM_IMAGES + ( image - gltextures ) ;
2010-10-22 09:12:38 +00:00
R_Bind ( image - > texnum ) ;
2010-10-20 09:02:21 +00:00
if ( bits = = 8 )
{
2010-10-22 09:12:38 +00:00
image - > has_alpha = R_Upload8 ( pic , width , height , ( image - > type ! = it_pic & & image - > type ! = it_sky ) ,
2010-10-20 09:02:21 +00:00
image - > type = = it_sky ) ;
}
2009-03-05 09:07:55 +00:00
else
2010-10-20 09:02:21 +00:00
{
2010-10-22 09:12:38 +00:00
image - > has_alpha = R_Upload32 ( ( unsigned * ) pic , width , height , ( image - > type ! = it_pic & & image - > type ! = it_sky ) ) ;
2010-10-20 09:02:21 +00:00
}
image - > upload_width = upload_width ; /* after power of 2 and scales */
2009-03-05 09:07:55 +00:00
image - > upload_height = upload_height ;
image - > paletted = uploaded_paletted ;
2012-03-12 08:53:22 +00:00
if ( realwidth & & realheight )
{
if ( ( realwidth < = image - > width ) & & ( realheight < = image - > height ) )
{
image - > width = realwidth ;
image - > height = realheight ;
}
else
{
ri . Con_Printf ( PRINT_DEVELOPER , " Warning, image '%s' has hi-res replacement smaller than the original! (%d x %d) < (%d x %d) \n " , name , image - > width , image - > height , realwidth , realheight ) ;
}
}
2009-03-05 09:07:55 +00:00
image - > sl = 0 ;
image - > sh = 1 ;
image - > tl = 0 ;
image - > th = 1 ;
}
2010-10-20 09:02:21 +00:00
return ( image ) ;
2009-03-05 09:07:55 +00:00
}
/*
2010-10-20 09:02:21 +00:00
* Finds or loads the given image
*/
image_t *
2010-10-22 09:12:38 +00:00
R_FindImage ( char * name , imagetype_t type )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
image_t * image ;
int i , len ;
byte * pic , * palette ;
int width , height ;
2012-06-01 15:59:00 +00:00
int realwidth = 0 , realheight = 0 ;
2009-03-05 09:07:55 +00:00
char * ptr ;
2012-03-11 19:01:49 +00:00
char namewe [ 256 ] ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
if ( ! name )
{
return ( NULL ) ;
2009-03-05 09:07:55 +00:00
}
2012-04-29 13:57:33 +00:00
2012-03-12 08:11:22 +00:00
len = strlen ( name ) ;
2009-03-05 09:07:55 +00:00
2012-03-12 08:11:22 +00:00
/* Remove the extension */
2012-03-11 19:01:49 +00:00
memset ( namewe , 0 , 256 ) ;
2012-03-12 08:11:22 +00:00
memcpy ( namewe , name , len - 4 ) ;
2010-10-20 09:02:21 +00:00
if ( len < 5 )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
return ( NULL ) ;
}
/* fix backslashes */
while ( ( ptr = strchr ( name , ' \\ ' ) ) )
{
* ptr = ' / ' ;
}
/* look for it */
for ( i = 0 , image = gltextures ; i < numgltextures ; i + + , image + + )
{
if ( ! strcmp ( name , image - > name ) )
2009-03-05 09:07:55 +00:00
{
image - > registration_sequence = registration_sequence ;
2010-10-20 09:02:21 +00:00
return ( image ) ;
2009-03-05 09:07:55 +00:00
}
}
2010-10-20 09:02:21 +00:00
/* load the pic from disk */
2009-03-05 09:07:55 +00:00
pic = NULL ;
palette = NULL ;
2010-10-20 09:02:21 +00:00
if ( ! strcmp ( name + len - 4 , " .pcx " ) )
2009-03-05 09:07:55 +00:00
{
2012-04-25 08:59:40 +00:00
# ifdef RETEXTURE
2012-03-12 09:54:04 +00:00
if ( gl_retexturing - > value )
2010-10-20 09:02:21 +00:00
{
2012-03-12 09:54:04 +00:00
GetPCXInfo ( name , & realwidth , & realheight ) ;
/* Try to load a TGA */
LoadTGA ( namewe , & pic , & width , & height ) ;
if ( ! pic )
{
/* JPEG if no TGA available */
LoadJPG ( namewe , & pic , & width , & height ) ;
}
else
{
/* Upload TGA */
2012-06-01 15:05:40 +00:00
R_LoadPic ( name , pic , width , realwidth , height , realheight , type , 32 ) ;
2012-03-12 09:54:04 +00:00
}
if ( ! pic )
{
/* PCX if no JPEG available (exists always) */
LoadPCX ( name , & pic , & palette , & width , & height ) ;
if ( ! pic )
{
/* No texture found */
return ( NULL ) ;
}
/* Upload the PCX */
2012-04-29 13:57:33 +00:00
image = R_LoadPic ( name , pic , width , 0 , height , 0 , type , 8 ) ;
2012-03-12 09:54:04 +00:00
}
else
{
2012-06-01 15:05:40 +00:00
/* Upload JPEG or TGA */
2012-03-12 09:54:04 +00:00
image = R_LoadPic ( name , pic , width , realwidth , height , realheight , type , 32 ) ;
}
2010-10-20 09:02:21 +00:00
}
2012-03-12 09:54:04 +00:00
else
2012-04-25 08:59:40 +00:00
# endif
2012-03-12 09:54:04 +00:00
{
LoadPCX ( name , & pic , & palette , & width , & height ) ;
2010-10-20 09:02:21 +00:00
2012-03-12 09:54:04 +00:00
if ( ! pic )
{
return ( NULL ) ;
}
image = R_LoadPic ( name , pic , width , 0 , height , 0 , type , 8 ) ;
}
2009-03-05 09:07:55 +00:00
}
2010-10-20 09:02:21 +00:00
else if ( ! strcmp ( name + len - 4 , " .wal " ) )
2009-03-05 09:07:55 +00:00
{
2012-04-25 08:59:40 +00:00
# ifdef RETEXTURE
2012-03-12 09:31:33 +00:00
if ( gl_retexturing - > value )
{
/* Get size of the original texture */
GetWalInfo ( name , & realwidth , & realheight ) ;
2012-03-11 19:01:49 +00:00
2012-03-12 09:31:33 +00:00
/* Try to load a TGA */
LoadTGA ( namewe , & pic , & width , & height ) ;
2012-03-12 08:11:22 +00:00
2012-03-12 09:31:33 +00:00
if ( ! pic )
{
/* JPEG if no TGA available */
LoadJPG ( namewe , & pic , & width , & height ) ;
}
else
{
/* Upload TGA */
2012-06-01 15:05:40 +00:00
R_LoadPic ( name , pic , width , realwidth , height , realheight , type , 32 ) ;
2012-03-12 09:31:33 +00:00
}
2012-03-11 19:01:49 +00:00
2012-03-12 09:31:33 +00:00
if ( ! pic )
{
/* WAL of no JPEG available (exists always) */
image = LoadWal ( namewe ) ;
}
else
{
2012-06-01 15:05:40 +00:00
/* Upload JPEG or TGA */
2012-03-12 09:31:33 +00:00
image = R_LoadPic ( name , pic , width , realwidth , height , realheight , type , 32 ) ;
}
if ( ! image )
{
/* No texture found */
return ( NULL ) ;
}
2012-03-11 19:01:49 +00:00
}
2012-03-12 08:11:22 +00:00
else
2012-04-25 08:59:40 +00:00
# endif
2012-03-12 08:11:22 +00:00
{
2012-03-12 09:31:33 +00:00
image = LoadWal ( name ) ;
2012-03-12 08:11:22 +00:00
2012-03-12 09:31:33 +00:00
if ( ! image )
{
/* No texture found */
return ( NULL ) ;
}
2012-03-12 08:11:22 +00:00
}
2009-03-05 09:07:55 +00:00
}
2010-10-20 09:02:21 +00:00
else if ( ! strcmp ( name + len - 4 , " .tga " ) )
2009-03-05 09:07:55 +00:00
{
2012-03-12 08:11:22 +00:00
LoadTGA ( name , & pic , & width , & height ) ;
2012-03-12 08:53:22 +00:00
image = R_LoadPic ( name , pic , width , realwidth , height , realwidth , type , 32 ) ;
2012-03-11 16:50:57 +00:00
}
else if ( ! strcmp ( name + len - 4 , " .jpg " ) )
{
2012-03-12 08:11:22 +00:00
LoadJPG ( name , & pic , & width , & height ) ;
2012-03-12 08:53:22 +00:00
image = R_LoadPic ( name , pic , width , realwidth , height , realheight , type , 32 ) ;
2009-03-05 09:07:55 +00:00
}
else
2010-10-20 09:02:21 +00:00
{
return ( NULL ) ;
}
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
if ( pic )
{
free ( pic ) ;
}
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
if ( palette )
{
free ( palette ) ;
}
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
return ( image ) ;
2009-03-05 09:07:55 +00:00
}
2010-10-20 09:02:21 +00:00
struct image_s *
R_RegisterSkin ( char * name )
2009-03-05 09:07:55 +00:00
{
2010-10-22 09:12:38 +00:00
return ( R_FindImage ( name , it_skin ) ) ;
2009-03-05 09:07:55 +00:00
}
/*
2010-10-25 12:33:55 +00:00
* Any image that was not touched on
2010-10-20 09:02:21 +00:00
* this registration sequence
* will be freed .
*/
void
2010-10-22 09:12:38 +00:00
R_FreeUnusedImages ( void )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
int i ;
image_t * image ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
/* never free r_notexture or particle texture */
2009-03-05 09:07:55 +00:00
r_notexture - > registration_sequence = registration_sequence ;
r_particletexture - > registration_sequence = registration_sequence ;
2010-10-20 09:02:21 +00:00
for ( i = 0 , image = gltextures ; i < numgltextures ; i + + , image + + )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
if ( image - > registration_sequence = = registration_sequence )
{
continue ; /* used this sequence */
}
if ( ! image - > registration_sequence )
{
continue ; /* free image_t slot */
}
if ( image - > type = = it_pic )
{
continue ; /* don't free pics */
}
/* free it */
qglDeleteTextures ( 1 , ( GLuint * ) & image - > texnum ) ;
memset ( image , 0 , sizeof ( * image ) ) ;
2009-03-05 09:07:55 +00:00
}
}
2010-10-20 09:02:21 +00:00
void
2010-10-22 09:12:38 +00:00
R_InitImages ( void )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
int i , j ;
float g = vid_gamma - > value ;
2009-03-05 09:07:55 +00:00
registration_sequence = 1 ;
2010-10-20 09:02:21 +00:00
/* init intensity conversions */
2010-10-25 15:57:39 +00:00
intensity = ri . Cvar_Get ( " intensity " , " 2 " , CVAR_ARCHIVE ) ;
2009-03-05 09:07:55 +00:00
if ( intensity - > value < = 1 )
2010-10-20 09:02:21 +00:00
{
2009-03-05 09:07:55 +00:00
ri . Cvar_Set ( " intensity " , " 1 " ) ;
2010-10-20 09:02:21 +00:00
}
2009-03-05 09:07:55 +00:00
gl_state . inverse_intensity = 1 / intensity - > value ;
2010-10-20 09:02:21 +00:00
Draw_GetPalette ( ) ;
2009-03-05 09:07:55 +00:00
if ( qglColorTableEXT )
{
2010-10-20 09:02:21 +00:00
ri . FS_LoadFile ( " pics/16to8.dat " , ( void * * ) & gl_state . d_16to8table ) ;
2009-03-05 09:07:55 +00:00
if ( ! gl_state . d_16to8table )
2010-10-20 09:02:21 +00:00
{
ri . Sys_Error ( ERR_FATAL , " Couldn't load pics/16to8.pcx " ) ;
}
2009-03-05 09:07:55 +00:00
}
for ( i = 0 ; i < 256 ; i + + )
{
2010-10-20 09:02:21 +00:00
if ( ( g = = 1 ) | | gl_state . hwgamma )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
gammatable [ i ] = i ;
2009-03-05 09:07:55 +00:00
}
else
{
float inf ;
2010-10-20 09:02:21 +00:00
inf = 255 * pow ( ( i + 0.5 ) / 255.5 , g ) + 0.5 ;
if ( inf < 0 )
{
2009-03-05 09:07:55 +00:00
inf = 0 ;
2010-10-20 09:02:21 +00:00
}
if ( inf > 255 )
{
2009-03-05 09:07:55 +00:00
inf = 255 ;
2010-10-20 09:02:21 +00:00
}
gammatable [ i ] = inf ;
2009-03-05 09:07:55 +00:00
}
}
2010-10-20 09:02:21 +00:00
for ( i = 0 ; i < 256 ; i + + )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
j = i * intensity - > value ;
if ( j > 255 )
{
2009-03-05 09:07:55 +00:00
j = 255 ;
2010-10-20 09:02:21 +00:00
}
intensitytable [ i ] = j ;
2009-03-05 09:07:55 +00:00
}
}
2010-10-20 09:02:21 +00:00
void
2010-10-22 09:12:38 +00:00
R_ShutdownImages ( void )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
int i ;
image_t * image ;
2009-03-05 09:07:55 +00:00
2010-10-20 09:02:21 +00:00
for ( i = 0 , image = gltextures ; i < numgltextures ; i + + , image + + )
2009-03-05 09:07:55 +00:00
{
2010-10-20 09:02:21 +00:00
if ( ! image - > registration_sequence )
{
continue ; /* free image_t slot */
}
/* free it */
qglDeleteTextures ( 1 , ( GLuint * ) & image - > texnum ) ;
memset ( image , 0 , sizeof ( * image ) ) ;
2009-03-05 09:07:55 +00:00
}
}