2009-03-05 09:07:55 +00:00
|
|
|
/*
|
2010-10-20 09:02:21 +00:00
|
|
|
* Copyright (C) 1997-2001 Id Software, Inc.
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*/
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
/*
|
|
|
|
Spalten in:
|
|
|
|
- gl_scrap.c
|
|
|
|
- gl_pcx.c
|
|
|
|
- gl_tga.c
|
|
|
|
- gl_wal.c
|
|
|
|
*/
|
|
|
|
#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 */
|
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-20 09:02:21 +00:00
|
|
|
qboolean GL_Upload8 ( byte *data, int width, int height, qboolean mipmap, qboolean is_sky );
|
|
|
|
qboolean GL_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-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 },
|
|
|
|
{ "GL_RGB2", GL_RGB2_EXT },
|
|
|
|
};
|
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 ) )
|
|
|
|
|
|
|
|
void
|
|
|
|
GL_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
|
|
|
|
GL_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
|
|
|
|
GL_MBind ( GLenum target, int texnum )
|
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
|
|
|
|
2009-03-05 09:07:55 +00:00
|
|
|
GL_Bind( texnum );
|
|
|
|
}
|
2010-10-20 09:02:21 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
GL_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
|
|
|
|
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-20 09:02:21 +00:00
|
|
|
GL_Bind( glt->texnum );
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
void
|
|
|
|
GL_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
|
|
|
|
GL_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
|
|
|
|
GL_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
|
|
|
* scrap allocation
|
|
|
|
*
|
|
|
|
* Allocate all the little status bar obejcts into a single texture
|
|
|
|
* to crutch up inefficient hardware / drivers
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define MAX_SCRAPS 1
|
|
|
|
#define BLOCK_WIDTH 256
|
|
|
|
#define BLOCK_HEIGHT 256
|
|
|
|
|
|
|
|
int scrap_allocated [ MAX_SCRAPS ] [ BLOCK_WIDTH ];
|
|
|
|
byte scrap_texels [ MAX_SCRAPS ] [ BLOCK_WIDTH * BLOCK_HEIGHT ];
|
|
|
|
qboolean scrap_dirty;
|
|
|
|
|
|
|
|
/* returns a texture number and the position inside it */
|
|
|
|
int
|
|
|
|
Scrap_AllocBlock ( int w, int h, int *x, int *y )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
int i, j;
|
|
|
|
int best, best2;
|
|
|
|
int texnum;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
for ( texnum = 0; texnum < MAX_SCRAPS; texnum++ )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
|
|
|
best = BLOCK_HEIGHT;
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
for ( i = 0; i < BLOCK_WIDTH - w; i++ )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
|
|
|
best2 = 0;
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
for ( j = 0; j < w; j++ )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
if ( scrap_allocated [ texnum ] [ i + j ] >= best )
|
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
break;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( scrap_allocated [ texnum ] [ i + j ] > best2 )
|
|
|
|
{
|
|
|
|
best2 = scrap_allocated [ texnum ] [ i + j ];
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
2010-10-20 09:02:21 +00:00
|
|
|
|
|
|
|
if ( j == w )
|
|
|
|
{ /* this is a valid spot */
|
2009-03-05 09:07:55 +00:00
|
|
|
*x = i;
|
|
|
|
*y = best = best2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
if ( best + h > BLOCK_HEIGHT )
|
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
continue;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
for ( i = 0; i < w; i++ )
|
|
|
|
{
|
|
|
|
scrap_allocated [ texnum ] [ *x + i ] = best + h;
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
return ( texnum );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
return ( -1 );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
int scrap_uploads;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
void
|
|
|
|
Scrap_Upload ( void )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
|
|
|
scrap_uploads++;
|
2010-10-20 09:02:21 +00:00
|
|
|
GL_Bind( TEXNUM_SCRAPS );
|
|
|
|
GL_Upload8( scrap_texels [ 0 ], BLOCK_WIDTH, BLOCK_HEIGHT, false, false );
|
2009-03-05 09:07:55 +00:00
|
|
|
scrap_dirty = false;
|
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
void
|
|
|
|
LoadPCX ( char *filename, byte **pic, byte **palette, int *width, int *height )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
byte *raw;
|
|
|
|
pcx_t *pcx;
|
|
|
|
int x, y;
|
|
|
|
int len;
|
|
|
|
int dataByte, runLength;
|
|
|
|
byte *out, *pix;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
*pic = NULL;
|
|
|
|
*palette = NULL;
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
/* load the file */
|
|
|
|
len = ri.FS_LoadFile( filename, (void **) &raw );
|
|
|
|
|
|
|
|
if ( !raw )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
ri.Con_Printf( PRINT_DEVELOPER, "Bad pcx file %s\n", filename );
|
2009-03-05 09:07:55 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
/* parse the PCX file */
|
|
|
|
pcx = (pcx_t *) raw;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
pcx->xmin = LittleShort( pcx->xmin );
|
|
|
|
pcx->ymin = LittleShort( pcx->ymin );
|
|
|
|
pcx->xmax = LittleShort( pcx->xmax );
|
|
|
|
pcx->ymax = LittleShort( pcx->ymax );
|
|
|
|
pcx->hres = LittleShort( pcx->hres );
|
|
|
|
pcx->vres = LittleShort( pcx->vres );
|
|
|
|
pcx->bytes_per_line = LittleShort( pcx->bytes_per_line );
|
|
|
|
pcx->palette_type = LittleShort( pcx->palette_type );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
raw = &pcx->data;
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
if ( ( pcx->manufacturer != 0x0a ) ||
|
|
|
|
( pcx->version != 5 ) ||
|
|
|
|
( pcx->encoding != 1 ) ||
|
|
|
|
( pcx->bits_per_pixel != 8 ) ||
|
|
|
|
( pcx->xmax >= 640 ) ||
|
|
|
|
( pcx->ymax >= 480 ) )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
ri.Con_Printf( PRINT_ALL, "Bad pcx file %s\n", filename );
|
2009-03-05 09:07:55 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
out = malloc( ( pcx->ymax + 1 ) * ( pcx->xmax + 1 ) );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
*pic = out;
|
|
|
|
|
|
|
|
pix = out;
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
if ( palette )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
*palette = malloc( 768 );
|
|
|
|
memcpy( *palette, (byte *) pcx + len - 768, 768 );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
if ( width )
|
|
|
|
{
|
|
|
|
*width = pcx->xmax + 1;
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
if ( height )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
*height = pcx->ymax + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( y = 0; y <= pcx->ymax; y++, pix += pcx->xmax + 1 )
|
|
|
|
{
|
|
|
|
for ( x = 0; x <= pcx->xmax; )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
|
|
|
dataByte = *raw++;
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
if ( ( dataByte & 0xC0 ) == 0xC0 )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
|
|
|
runLength = dataByte & 0x3F;
|
|
|
|
dataByte = *raw++;
|
|
|
|
}
|
|
|
|
else
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
runLength = 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
|
|
|
while ( runLength-- > 0 )
|
|
|
|
{
|
|
|
|
pix [ x++ ] = dataByte;
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
if ( raw - (byte *) pcx > len )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
ri.Con_Printf( PRINT_DEVELOPER, "PCX file %s was malformed", filename );
|
|
|
|
free( *pic );
|
2009-03-05 09:07:55 +00:00
|
|
|
*pic = NULL;
|
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
ri.FS_FreeFile( pcx );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
typedef struct _TargaHeader
|
|
|
|
{
|
|
|
|
unsigned char id_length, colormap_type, image_type;
|
|
|
|
unsigned short colormap_index, colormap_length;
|
|
|
|
unsigned char colormap_size;
|
|
|
|
unsigned short x_origin, y_origin, width, height;
|
|
|
|
unsigned char pixel_size, attributes;
|
2009-03-05 09:07:55 +00:00
|
|
|
} TargaHeader;
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
void
|
|
|
|
LoadTGA ( char *name, byte **pic, int *width, int *height )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
int columns, rows, numPixels;
|
|
|
|
byte *pixbuf;
|
|
|
|
int row, column;
|
|
|
|
byte *buf_p;
|
|
|
|
byte *buffer;
|
|
|
|
int length;
|
|
|
|
TargaHeader targa_header;
|
|
|
|
byte *targa_rgba;
|
|
|
|
byte tmp [ 2 ];
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
*pic = NULL;
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
/* load the file */
|
|
|
|
length = ri.FS_LoadFile( name, (void **) &buffer );
|
|
|
|
|
|
|
|
if ( !buffer )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
ri.Con_Printf( PRINT_DEVELOPER, "Bad tga file %s\n", name );
|
2009-03-05 09:07:55 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
buf_p = buffer;
|
|
|
|
|
|
|
|
targa_header.id_length = *buf_p++;
|
|
|
|
targa_header.colormap_type = *buf_p++;
|
|
|
|
targa_header.image_type = *buf_p++;
|
2010-10-20 09:02:21 +00:00
|
|
|
|
|
|
|
tmp [ 0 ] = buf_p [ 0 ];
|
|
|
|
tmp [ 1 ] = buf_p [ 1 ];
|
|
|
|
targa_header.colormap_index = LittleShort( *( (short *) tmp ) );
|
|
|
|
buf_p += 2;
|
|
|
|
tmp [ 0 ] = buf_p [ 0 ];
|
|
|
|
tmp [ 1 ] = buf_p [ 1 ];
|
|
|
|
targa_header.colormap_length = LittleShort( *( (short *) tmp ) );
|
|
|
|
buf_p += 2;
|
2009-03-05 09:07:55 +00:00
|
|
|
targa_header.colormap_size = *buf_p++;
|
2010-10-20 09:02:21 +00:00
|
|
|
targa_header.x_origin = LittleShort( *( (short *) buf_p ) );
|
|
|
|
buf_p += 2;
|
|
|
|
targa_header.y_origin = LittleShort( *( (short *) buf_p ) );
|
|
|
|
buf_p += 2;
|
|
|
|
targa_header.width = LittleShort( *( (short *) buf_p ) );
|
|
|
|
buf_p += 2;
|
|
|
|
targa_header.height = LittleShort( *( (short *) buf_p ) );
|
|
|
|
buf_p += 2;
|
2009-03-05 09:07:55 +00:00
|
|
|
targa_header.pixel_size = *buf_p++;
|
|
|
|
targa_header.attributes = *buf_p++;
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
if ( ( targa_header.image_type != 2 ) &&
|
|
|
|
( targa_header.image_type != 10 ) )
|
|
|
|
{
|
|
|
|
ri.Sys_Error( ERR_DROP, "LoadTGA: Only type 2 and 10 targa RGB images supported\n" );
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
if ( ( targa_header.colormap_type != 0 ) ||
|
|
|
|
( ( targa_header.pixel_size != 32 ) && ( targa_header.pixel_size != 24 ) ) )
|
|
|
|
{
|
|
|
|
ri.Sys_Error( ERR_DROP, "LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n" );
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
columns = targa_header.width;
|
|
|
|
rows = targa_header.height;
|
|
|
|
numPixels = columns * rows;
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
if ( width )
|
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
*width = columns;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( height )
|
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
*height = rows;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
targa_rgba = malloc( numPixels * 4 );
|
2009-03-05 09:07:55 +00:00
|
|
|
*pic = targa_rgba;
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
if ( targa_header.id_length != 0 )
|
|
|
|
{
|
|
|
|
buf_p += targa_header.id_length; /* skip TARGA image comment */
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( targa_header.image_type == 2 ) /* Uncompressed, RGB images */
|
|
|
|
{
|
|
|
|
for ( row = rows - 1; row >= 0; row-- )
|
|
|
|
{
|
|
|
|
pixbuf = targa_rgba + row * columns * 4;
|
|
|
|
|
|
|
|
for ( column = 0; column < columns; column++ )
|
|
|
|
{
|
|
|
|
unsigned char red, green, blue, alphabyte;
|
|
|
|
|
|
|
|
switch ( targa_header.pixel_size )
|
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
case 24:
|
2010-10-20 09:02:21 +00:00
|
|
|
|
|
|
|
blue = *buf_p++;
|
|
|
|
green = *buf_p++;
|
|
|
|
red = *buf_p++;
|
|
|
|
*pixbuf++ = red;
|
|
|
|
*pixbuf++ = green;
|
|
|
|
*pixbuf++ = blue;
|
|
|
|
*pixbuf++ = 255;
|
|
|
|
break;
|
|
|
|
case 32:
|
|
|
|
blue = *buf_p++;
|
|
|
|
green = *buf_p++;
|
|
|
|
red = *buf_p++;
|
|
|
|
alphabyte = *buf_p++;
|
|
|
|
*pixbuf++ = red;
|
|
|
|
*pixbuf++ = green;
|
|
|
|
*pixbuf++ = blue;
|
|
|
|
*pixbuf++ = alphabyte;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ( targa_header.image_type == 10 ) /* Runlength encoded RGB images */
|
|
|
|
{
|
|
|
|
unsigned char red, green, blue, alphabyte, packetHeader, packetSize, j;
|
|
|
|
|
|
|
|
for ( row = rows - 1; row >= 0; row-- )
|
|
|
|
{
|
|
|
|
pixbuf = targa_rgba + row * columns * 4;
|
|
|
|
|
|
|
|
for ( column = 0; column < columns; )
|
|
|
|
{
|
|
|
|
packetHeader = *buf_p++;
|
|
|
|
packetSize = 1 + ( packetHeader & 0x7f );
|
|
|
|
|
|
|
|
if ( packetHeader & 0x80 ) /* run-length packet */
|
|
|
|
{
|
|
|
|
switch ( targa_header.pixel_size )
|
|
|
|
{
|
|
|
|
case 24:
|
2009-03-05 09:07:55 +00:00
|
|
|
blue = *buf_p++;
|
|
|
|
green = *buf_p++;
|
|
|
|
red = *buf_p++;
|
2010-10-20 09:02:21 +00:00
|
|
|
alphabyte = 255;
|
2009-03-05 09:07:55 +00:00
|
|
|
break;
|
2010-10-20 09:02:21 +00:00
|
|
|
case 32:
|
2009-03-05 09:07:55 +00:00
|
|
|
blue = *buf_p++;
|
|
|
|
green = *buf_p++;
|
|
|
|
red = *buf_p++;
|
|
|
|
alphabyte = *buf_p++;
|
|
|
|
break;
|
|
|
|
default:
|
2010-10-20 09:02:21 +00:00
|
|
|
blue = 0;
|
|
|
|
green = 0;
|
|
|
|
red = 0;
|
|
|
|
alphabyte = 0;
|
|
|
|
break;
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
2010-10-20 09:02:21 +00:00
|
|
|
|
|
|
|
for ( j = 0; j < packetSize; j++ )
|
|
|
|
{
|
|
|
|
*pixbuf++ = red;
|
|
|
|
*pixbuf++ = green;
|
|
|
|
*pixbuf++ = blue;
|
|
|
|
*pixbuf++ = alphabyte;
|
2009-03-05 09:07:55 +00:00
|
|
|
column++;
|
2010-10-20 09:02:21 +00:00
|
|
|
|
|
|
|
/* run spans across rows */
|
|
|
|
if ( column == columns )
|
|
|
|
{
|
|
|
|
column = 0;
|
|
|
|
|
|
|
|
if ( row > 0 )
|
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
row--;
|
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
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
goto breakOut;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pixbuf = targa_rgba + row * columns * 4;
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-10-20 09:02:21 +00:00
|
|
|
else /* non run-length packet */
|
|
|
|
{
|
|
|
|
for ( j = 0; j < packetSize; j++ )
|
|
|
|
{
|
|
|
|
switch ( targa_header.pixel_size )
|
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
case 24:
|
2010-10-20 09:02:21 +00:00
|
|
|
blue = *buf_p++;
|
|
|
|
green = *buf_p++;
|
|
|
|
red = *buf_p++;
|
|
|
|
*pixbuf++ = red;
|
|
|
|
*pixbuf++ = green;
|
|
|
|
*pixbuf++ = blue;
|
|
|
|
*pixbuf++ = 255;
|
|
|
|
break;
|
2009-03-05 09:07:55 +00:00
|
|
|
case 32:
|
2010-10-20 09:02:21 +00:00
|
|
|
blue = *buf_p++;
|
|
|
|
green = *buf_p++;
|
|
|
|
red = *buf_p++;
|
|
|
|
alphabyte = *buf_p++;
|
|
|
|
*pixbuf++ = red;
|
|
|
|
*pixbuf++ = green;
|
|
|
|
*pixbuf++ = blue;
|
|
|
|
*pixbuf++ = alphabyte;
|
|
|
|
break;
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
2010-10-20 09:02:21 +00:00
|
|
|
|
2009-03-05 09:07:55 +00:00
|
|
|
column++;
|
2010-10-20 09:02:21 +00:00
|
|
|
|
|
|
|
if ( column == columns ) /* pixel packet run spans across rows */
|
|
|
|
{
|
|
|
|
column = 0;
|
|
|
|
|
|
|
|
if ( row > 0 )
|
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
row--;
|
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
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
goto breakOut;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pixbuf = targa_rgba + row * columns * 4;
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-10-20 09:02:21 +00:00
|
|
|
|
|
|
|
breakOut:;
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
ri.FS_FreeFile( buffer );
|
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
|
|
|
|
*/
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
short x, y;
|
2009-03-05 09:07:55 +00:00
|
|
|
} floodfill_t;
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
/* must be a power of 2 */
|
2009-03-05 09:07:55 +00:00
|
|
|
#define FLOODFILL_FIFO_SIZE 0x1000
|
2010-10-20 09:02:21 +00:00
|
|
|
#define FLOODFILL_FIFO_MASK ( FLOODFILL_FIFO_SIZE - 1 )
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
#define FLOODFILL_STEP( off, dx, dy ) \
|
|
|
|
{ \
|
2010-10-20 09:02:21 +00:00
|
|
|
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 ]; \
|
|
|
|
} \
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
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
|
|
|
|
GL_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 );
|
2009-03-05 09:07:55 +00:00
|
|
|
frac = fracstep >> 1;
|
2010-10-20 09:02:21 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
GL_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
|
|
|
|
GL_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
|
|
|
|
GL_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
|
|
|
int upload_width, upload_height;
|
2009-03-05 09:07:55 +00:00
|
|
|
qboolean uploaded_paletted;
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
qboolean
|
|
|
|
GL_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 ];
|
|
|
|
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 )
|
|
|
|
{
|
|
|
|
ri.Sys_Error( ERR_DROP, "GL_Upload32: too big" );
|
|
|
|
}
|
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-20 09:02:21 +00:00
|
|
|
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
|
|
|
{
|
|
|
|
GL_ResampleTexture( data, width, height, scaled, scaled_width, scaled_height );
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
GL_LightScaleTexture( scaled, scaled_width, scaled_height, !mipmap );
|
2009-10-04 10:58:42 +00:00
|
|
|
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-20 09:02:21 +00:00
|
|
|
GL_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-20 09:02:21 +00:00
|
|
|
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-20 09:02:21 +00:00
|
|
|
done:;
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
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
|
|
|
|
GL_Upload8 ( byte *data, int width, int height, qboolean mipmap, qboolean is_sky )
|
|
|
|
{
|
|
|
|
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 )
|
|
|
|
{
|
|
|
|
ri.Sys_Error( ERR_DROP, "GL_Upload8: too large" );
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( i = 0; i < s; i++ )
|
|
|
|
{
|
|
|
|
p = data [ i ];
|
|
|
|
trans [ i ] = d_8to24table [ p ];
|
|
|
|
|
|
|
|
/* transparent, so scan around for another color
|
|
|
|
to avoid alpha fringes */
|
|
|
|
if ( p == 255 )
|
|
|
|
{
|
|
|
|
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 ];
|
|
|
|
}
|
2009-10-04 10:58:42 +00:00
|
|
|
else
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2009-10-04 10:58:42 +00:00
|
|
|
p = 0;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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 ];
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
2009-10-04 10:58:42 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
return ( GL_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 *
|
|
|
|
GL_LoadPic ( char *name, byte *pic, int width, int height, 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 );
|
|
|
|
GL_Bind( image->texnum );
|
|
|
|
|
|
|
|
if ( bits == 8 )
|
|
|
|
{
|
|
|
|
image->has_alpha = GL_Upload8( pic, width, height, ( image->type != it_pic && image->type != it_sky ),
|
|
|
|
image->type == it_sky );
|
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
else
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
|
|
|
image->has_alpha = GL_Upload32( (unsigned *) pic, width, height, ( image->type != it_pic && image->type != it_sky ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
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
|
|
|
image_t *
|
|
|
|
GL_LoadWal ( char *name )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
miptex_t *mt;
|
|
|
|
int width, height, ofs;
|
|
|
|
image_t *image;
|
|
|
|
|
|
|
|
ri.FS_LoadFile( name, (void **) &mt );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
if ( !mt )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
ri.Con_Printf( PRINT_ALL, "GL_FindImage: can't load %s\n", name );
|
|
|
|
return ( r_notexture );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
width = LittleLong( mt->width );
|
|
|
|
height = LittleLong( mt->height );
|
|
|
|
ofs = LittleLong( mt->offsets [ 0 ] );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
image = GL_LoadPic( name, (byte *) mt + ofs, width, height, it_wall, 8 );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
ri.FS_FreeFile( (void *) mt );
|
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
|
|
|
* Finds or loads the given image
|
|
|
|
*/
|
|
|
|
image_t *
|
|
|
|
GL_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;
|
2009-03-05 09:07:55 +00:00
|
|
|
char *ptr;
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
if ( !name )
|
|
|
|
{
|
|
|
|
return ( NULL );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
len = strlen( name );
|
|
|
|
|
|
|
|
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
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
LoadPCX( name, &pic, &palette, &width, &height );
|
|
|
|
|
|
|
|
if ( !pic )
|
|
|
|
{
|
|
|
|
return ( NULL );
|
|
|
|
}
|
|
|
|
|
|
|
|
image = GL_LoadPic( name, pic, width, height, 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
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
image = GL_LoadWal( name );
|
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
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
LoadTGA( name, &pic, &width, &height );
|
|
|
|
|
|
|
|
if ( !pic )
|
|
|
|
{
|
|
|
|
return ( NULL );
|
|
|
|
}
|
|
|
|
|
|
|
|
image = GL_LoadPic( name, pic, width, height, 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-20 09:02:21 +00:00
|
|
|
return ( GL_FindImage( name, it_skin ) );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-10-20 09:02:21 +00:00
|
|
|
* Any image that was not touched on
|
|
|
|
* this registration sequence
|
|
|
|
* will be freed.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
GL_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
|
|
|
int
|
|
|
|
Draw_GetPalette ( void )
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
int i;
|
|
|
|
int r, g, b;
|
|
|
|
unsigned v;
|
|
|
|
byte *pic, *pal;
|
|
|
|
int width, height;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
/* get the palette */
|
|
|
|
LoadPCX( "pics/colormap.pcx", &pic, &pal, &width, &height );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
if ( !pal )
|
|
|
|
{
|
|
|
|
ri.Sys_Error( ERR_FATAL, "Couldn't load pics/colormap.pcx" );
|
|
|
|
}
|
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
|
|
|
r = pal [ i * 3 + 0 ];
|
|
|
|
g = pal [ i * 3 + 1 ];
|
|
|
|
b = pal [ i * 3 + 2 ];
|
|
|
|
|
|
|
|
v = ( 255 << 24 ) + ( r << 0 ) + ( g << 8 ) + ( b << 16 );
|
|
|
|
d_8to24table [ i ] = LittleLong( v );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
d_8to24table [ 255 ] &= LittleLong( 0xffffff ); /* 255 is transparent */
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
free( pic );
|
|
|
|
free( pal );
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
return ( 0 );
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
void
|
|
|
|
GL_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 */
|
|
|
|
intensity = ri.Cvar_Get( "intensity", "2", 0 );
|
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
|
|
|
}
|
|
|
|
|
|
|
|
if ( gl_config.renderer & ( GL_RENDERER_VOODOO | GL_RENDERER_VOODOO2 ) )
|
|
|
|
{
|
|
|
|
g = 1.0F;
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
GL_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
|
|
|
}
|
|
|
|
}
|
|
|
|
|