Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

gl_image.c (33954B)


      1 /*
      2 Copyright (C) 1997-2001 Id Software, Inc.
      3 
      4 This program is free software; you can redistribute it and/or
      5 modify it under the terms of the GNU General Public License
      6 as published by the Free Software Foundation; either version 2
      7 of the License, or (at your option) any later version.
      8 
      9 This program is distributed in the hope that it will be useful,
     10 but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
     12 
     13 See the GNU General Public License for more details.
     14 
     15 You should have received a copy of the GNU General Public License
     16 along with this program; if not, write to the Free Software
     17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     18 
     19 */
     20 
     21 #include "gl_local.h"
     22 
     23 image_t		gltextures[MAX_GLTEXTURES];
     24 int			numgltextures;
     25 int			base_textureid;		// gltextures[i] = base_textureid+i
     26 
     27 static byte			 intensitytable[256];
     28 static unsigned char gammatable[256];
     29 
     30 cvar_t		*intensity;
     31 
     32 unsigned	d_8to24table[256];
     33 
     34 qboolean GL_Upload8 (byte *data, int width, int height,  qboolean mipmap, qboolean is_sky );
     35 qboolean GL_Upload32 (unsigned *data, int width, int height,  qboolean mipmap);
     36 
     37 
     38 int		gl_solid_format = 3;
     39 int		gl_alpha_format = 4;
     40 
     41 int		gl_tex_solid_format = 3;
     42 int		gl_tex_alpha_format = 4;
     43 
     44 int		gl_filter_min = GL_LINEAR_MIPMAP_NEAREST;
     45 int		gl_filter_max = GL_LINEAR;
     46 
     47 void GL_SetTexturePalette( unsigned palette[256] )
     48 {
     49 	int i;
     50 	unsigned char temptable[768];
     51 
     52 	for ( i = 0; i < 256; i++ )
     53 	{
     54 		temptable[i*3+0] = ( palette[i] >> 0 ) & 0xff;
     55 		temptable[i*3+1] = ( palette[i] >> 8 ) & 0xff;
     56 		temptable[i*3+2] = ( palette[i] >> 16 ) & 0xff;
     57 	}
     58 
     59 	if ( qglColorTableEXT && gl_ext_palettedtexture->value )
     60 	{
     61 		qglColorTableEXT( GL_SHARED_TEXTURE_PALETTE_EXT,
     62 						   GL_RGB,
     63 						   256,
     64 						   GL_RGB,
     65 						   GL_UNSIGNED_BYTE,
     66 						   temptable );
     67 	}
     68 }
     69 
     70 void GL_EnableMultitexture( qboolean enable )
     71 {
     72 	if ( !qglSelectTextureSGIS )
     73 		return;
     74 
     75 	if ( enable )
     76 	{
     77 		GL_SelectTexture( GL_TEXTURE1_SGIS );
     78 		qglEnable( GL_TEXTURE_2D );
     79 		GL_TexEnv( GL_REPLACE );
     80 	}
     81 	else
     82 	{
     83 		GL_SelectTexture( GL_TEXTURE1_SGIS );
     84 		qglDisable( GL_TEXTURE_2D );
     85 		GL_TexEnv( GL_REPLACE );
     86 	}
     87 	GL_SelectTexture( GL_TEXTURE0_SGIS );
     88 	GL_TexEnv( GL_REPLACE );
     89 }
     90 
     91 void GL_SelectTexture( GLenum texture )
     92 {
     93 	int tmu;
     94 
     95 	if ( !qglSelectTextureSGIS )
     96 		return;
     97 
     98 	if ( texture == GL_TEXTURE0_SGIS )
     99 		tmu = 0;
    100 	else
    101 		tmu = 1;
    102 
    103 	if ( tmu == gl_state.currenttmu )
    104 		return;
    105 
    106 	gl_state.currenttmu = tmu;
    107 
    108 	if ( tmu == 0 )
    109 		qglSelectTextureSGIS( GL_TEXTURE0_SGIS );
    110 	else
    111 		qglSelectTextureSGIS( GL_TEXTURE1_SGIS );
    112 }
    113 
    114 void GL_TexEnv( GLenum mode )
    115 {
    116 	static int lastmodes[2] = { -1, -1 };
    117 
    118 	if ( mode != lastmodes[gl_state.currenttmu] )
    119 	{
    120 		qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode );
    121 		lastmodes[gl_state.currenttmu] = mode;
    122 	}
    123 }
    124 
    125 void GL_Bind (int texnum)
    126 {
    127 	extern	image_t	*draw_chars;
    128 
    129 	if (gl_nobind->value && draw_chars)		// performance evaluation option
    130 		texnum = draw_chars->texnum;
    131 	if ( gl_state.currenttextures[gl_state.currenttmu] == texnum)
    132 		return;
    133 	gl_state.currenttextures[gl_state.currenttmu] = texnum;
    134 	qglBindTexture (GL_TEXTURE_2D, texnum);
    135 }
    136 
    137 void GL_MBind( GLenum target, int texnum )
    138 {
    139 	GL_SelectTexture( target );
    140 	if ( target == GL_TEXTURE0_SGIS )
    141 	{
    142 		if ( gl_state.currenttextures[0] == texnum )
    143 			return;
    144 	}
    145 	else
    146 	{
    147 		if ( gl_state.currenttextures[1] == texnum )
    148 			return;
    149 	}
    150 	GL_Bind( texnum );
    151 }
    152 
    153 typedef struct
    154 {
    155 	char *name;
    156 	int	minimize, maximize;
    157 } glmode_t;
    158 
    159 glmode_t modes[] = {
    160 	{"GL_NEAREST", GL_NEAREST, GL_NEAREST},
    161 	{"GL_LINEAR", GL_LINEAR, GL_LINEAR},
    162 	{"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
    163 	{"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
    164 	{"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
    165 	{"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
    166 };
    167 
    168 #define NUM_GL_MODES (sizeof(modes) / sizeof (glmode_t))
    169 
    170 typedef struct
    171 {
    172 	char *name;
    173 	int mode;
    174 } gltmode_t;
    175 
    176 gltmode_t gl_alpha_modes[] = {
    177 	{"default", 4},
    178 	{"GL_RGBA", GL_RGBA},
    179 	{"GL_RGBA8", GL_RGBA8},
    180 	{"GL_RGB5_A1", GL_RGB5_A1},
    181 	{"GL_RGBA4", GL_RGBA4},
    182 	{"GL_RGBA2", GL_RGBA2},
    183 };
    184 
    185 #define NUM_GL_ALPHA_MODES (sizeof(gl_alpha_modes) / sizeof (gltmode_t))
    186 
    187 gltmode_t gl_solid_modes[] = {
    188 	{"default", 3},
    189 	{"GL_RGB", GL_RGB},
    190 	{"GL_RGB8", GL_RGB8},
    191 	{"GL_RGB5", GL_RGB5},
    192 	{"GL_RGB4", GL_RGB4},
    193 	{"GL_R3_G3_B2", GL_R3_G3_B2},
    194 #ifdef GL_RGB2_EXT
    195 	{"GL_RGB2", GL_RGB2_EXT},
    196 #endif
    197 };
    198 
    199 #define NUM_GL_SOLID_MODES (sizeof(gl_solid_modes) / sizeof (gltmode_t))
    200 
    201 /*
    202 ===============
    203 GL_TextureMode
    204 ===============
    205 */
    206 void GL_TextureMode( char *string )
    207 {
    208 	int		i;
    209 	image_t	*glt;
    210 
    211 	for (i=0 ; i< NUM_GL_MODES ; i++)
    212 	{
    213 		if ( !Q_stricmp( modes[i].name, string ) )
    214 			break;
    215 	}
    216 
    217 	if (i == NUM_GL_MODES)
    218 	{
    219 		ri.Con_Printf (PRINT_ALL, "bad filter name\n");
    220 		return;
    221 	}
    222 
    223 	gl_filter_min = modes[i].minimize;
    224 	gl_filter_max = modes[i].maximize;
    225 
    226 	// change all the existing mipmap texture objects
    227 	for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
    228 	{
    229 		if (glt->type != it_pic && glt->type != it_sky )
    230 		{
    231 			GL_Bind (glt->texnum);
    232 			qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
    233 			qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
    234 		}
    235 	}
    236 }
    237 
    238 /*
    239 ===============
    240 GL_TextureAlphaMode
    241 ===============
    242 */
    243 void GL_TextureAlphaMode( char *string )
    244 {
    245 	int		i;
    246 
    247 	for (i=0 ; i< NUM_GL_ALPHA_MODES ; i++)
    248 	{
    249 		if ( !Q_stricmp( gl_alpha_modes[i].name, string ) )
    250 			break;
    251 	}
    252 
    253 	if (i == NUM_GL_ALPHA_MODES)
    254 	{
    255 		ri.Con_Printf (PRINT_ALL, "bad alpha texture mode name\n");
    256 		return;
    257 	}
    258 
    259 	gl_tex_alpha_format = gl_alpha_modes[i].mode;
    260 }
    261 
    262 /*
    263 ===============
    264 GL_TextureSolidMode
    265 ===============
    266 */
    267 void GL_TextureSolidMode( char *string )
    268 {
    269 	int		i;
    270 
    271 	for (i=0 ; i< NUM_GL_SOLID_MODES ; i++)
    272 	{
    273 		if ( !Q_stricmp( gl_solid_modes[i].name, string ) )
    274 			break;
    275 	}
    276 
    277 	if (i == NUM_GL_SOLID_MODES)
    278 	{
    279 		ri.Con_Printf (PRINT_ALL, "bad solid texture mode name\n");
    280 		return;
    281 	}
    282 
    283 	gl_tex_solid_format = gl_solid_modes[i].mode;
    284 }
    285 
    286 /*
    287 ===============
    288 GL_ImageList_f
    289 ===============
    290 */
    291 void	GL_ImageList_f (void)
    292 {
    293 	int		i;
    294 	image_t	*image;
    295 	int		texels;
    296 	const char *palstrings[2] =
    297 	{
    298 		"RGB",
    299 		"PAL"
    300 	};
    301 
    302 	ri.Con_Printf (PRINT_ALL, "------------------\n");
    303 	texels = 0;
    304 
    305 	for (i=0, image=gltextures ; i<numgltextures ; i++, image++)
    306 	{
    307 		if (image->texnum <= 0)
    308 			continue;
    309 		texels += image->upload_width*image->upload_height;
    310 		switch (image->type)
    311 		{
    312 		case it_skin:
    313 			ri.Con_Printf (PRINT_ALL, "M");
    314 			break;
    315 		case it_sprite:
    316 			ri.Con_Printf (PRINT_ALL, "S");
    317 			break;
    318 		case it_wall:
    319 			ri.Con_Printf (PRINT_ALL, "W");
    320 			break;
    321 		case it_pic:
    322 			ri.Con_Printf (PRINT_ALL, "P");
    323 			break;
    324 		default:
    325 			ri.Con_Printf (PRINT_ALL, " ");
    326 			break;
    327 		}
    328 
    329 		ri.Con_Printf (PRINT_ALL,  " %3i %3i %s: %s\n",
    330 			image->upload_width, image->upload_height, palstrings[image->paletted], image->name);
    331 	}
    332 	ri.Con_Printf (PRINT_ALL, "Total texel count (not counting mipmaps): %i\n", texels);
    333 }
    334 
    335 
    336 /*
    337 =============================================================================
    338 
    339   scrap allocation
    340 
    341   Allocate all the little status bar obejcts into a single texture
    342   to crutch up inefficient hardware / drivers
    343 
    344 =============================================================================
    345 */
    346 
    347 #define	MAX_SCRAPS		1
    348 #define	BLOCK_WIDTH		256
    349 #define	BLOCK_HEIGHT	256
    350 
    351 int			scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH];
    352 byte		scrap_texels[MAX_SCRAPS][BLOCK_WIDTH*BLOCK_HEIGHT];
    353 qboolean	scrap_dirty;
    354 
    355 // returns a texture number and the position inside it
    356 int Scrap_AllocBlock (int w, int h, int *x, int *y)
    357 {
    358 	int		i, j;
    359 	int		best, best2;
    360 	int		texnum;
    361 
    362 	for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++)
    363 	{
    364 		best = BLOCK_HEIGHT;
    365 
    366 		for (i=0 ; i<BLOCK_WIDTH-w ; i++)
    367 		{
    368 			best2 = 0;
    369 
    370 			for (j=0 ; j<w ; j++)
    371 			{
    372 				if (scrap_allocated[texnum][i+j] >= best)
    373 					break;
    374 				if (scrap_allocated[texnum][i+j] > best2)
    375 					best2 = scrap_allocated[texnum][i+j];
    376 			}
    377 			if (j == w)
    378 			{	// this is a valid spot
    379 				*x = i;
    380 				*y = best = best2;
    381 			}
    382 		}
    383 
    384 		if (best + h > BLOCK_HEIGHT)
    385 			continue;
    386 
    387 		for (i=0 ; i<w ; i++)
    388 			scrap_allocated[texnum][*x + i] = best + h;
    389 
    390 		return texnum;
    391 	}
    392 
    393 	return -1;
    394 //	Sys_Error ("Scrap_AllocBlock: full");
    395 }
    396 
    397 int	scrap_uploads;
    398 
    399 void Scrap_Upload (void)
    400 {
    401 	scrap_uploads++;
    402 	GL_Bind(TEXNUM_SCRAPS);
    403 	GL_Upload8 (scrap_texels[0], BLOCK_WIDTH, BLOCK_HEIGHT, false, false );
    404 	scrap_dirty = false;
    405 }
    406 
    407 /*
    408 =================================================================
    409 
    410 PCX LOADING
    411 
    412 =================================================================
    413 */
    414 
    415 
    416 /*
    417 ==============
    418 LoadPCX
    419 ==============
    420 */
    421 void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height)
    422 {
    423 	byte	*raw;
    424 	pcx_t	*pcx;
    425 	int		x, y;
    426 	int		len;
    427 	int		dataByte, runLength;
    428 	byte	*out, *pix;
    429 
    430 	*pic = NULL;
    431 	*palette = NULL;
    432 
    433 	//
    434 	// load the file
    435 	//
    436 	len = ri.FS_LoadFile (filename, (void **)&raw);
    437 	if (!raw)
    438 	{
    439 		ri.Con_Printf (PRINT_DEVELOPER, "Bad pcx file %s\n", filename);
    440 		return;
    441 	}
    442 
    443 	//
    444 	// parse the PCX file
    445 	//
    446 	pcx = (pcx_t *)raw;
    447 
    448     pcx->xmin = LittleShort(pcx->xmin);
    449     pcx->ymin = LittleShort(pcx->ymin);
    450     pcx->xmax = LittleShort(pcx->xmax);
    451     pcx->ymax = LittleShort(pcx->ymax);
    452     pcx->hres = LittleShort(pcx->hres);
    453     pcx->vres = LittleShort(pcx->vres);
    454     pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
    455     pcx->palette_type = LittleShort(pcx->palette_type);
    456 
    457 	raw = &pcx->data;
    458 
    459 	if (pcx->manufacturer != 0x0a
    460 		|| pcx->version != 5
    461 		|| pcx->encoding != 1
    462 		|| pcx->bits_per_pixel != 8
    463 		|| pcx->xmax >= 640
    464 		|| pcx->ymax >= 480)
    465 	{
    466 		ri.Con_Printf (PRINT_ALL, "Bad pcx file %s\n", filename);
    467 		return;
    468 	}
    469 
    470 	out = malloc ( (pcx->ymax+1) * (pcx->xmax+1) );
    471 
    472 	*pic = out;
    473 
    474 	pix = out;
    475 
    476 	if (palette)
    477 	{
    478 		*palette = malloc(768);
    479 		memcpy (*palette, (byte *)pcx + len - 768, 768);
    480 	}
    481 
    482 	if (width)
    483 		*width = pcx->xmax+1;
    484 	if (height)
    485 		*height = pcx->ymax+1;
    486 
    487 	for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1)
    488 	{
    489 		for (x=0 ; x<=pcx->xmax ; )
    490 		{
    491 			dataByte = *raw++;
    492 
    493 			if((dataByte & 0xC0) == 0xC0)
    494 			{
    495 				runLength = dataByte & 0x3F;
    496 				dataByte = *raw++;
    497 			}
    498 			else
    499 				runLength = 1;
    500 
    501 			while(runLength-- > 0)
    502 				pix[x++] = dataByte;
    503 		}
    504 
    505 	}
    506 
    507 	if ( raw - (byte *)pcx > len)
    508 	{
    509 		ri.Con_Printf (PRINT_DEVELOPER, "PCX file %s was malformed", filename);
    510 		free (*pic);
    511 		*pic = NULL;
    512 	}
    513 
    514 	ri.FS_FreeFile (pcx);
    515 }
    516 
    517 /*
    518 =========================================================
    519 
    520 TARGA LOADING
    521 
    522 =========================================================
    523 */
    524 
    525 typedef struct _TargaHeader {
    526 	unsigned char 	id_length, colormap_type, image_type;
    527 	unsigned short	colormap_index, colormap_length;
    528 	unsigned char	colormap_size;
    529 	unsigned short	x_origin, y_origin, width, height;
    530 	unsigned char	pixel_size, attributes;
    531 } TargaHeader;
    532 
    533 
    534 /*
    535 =============
    536 LoadTGA
    537 =============
    538 */
    539 void LoadTGA (char *name, byte **pic, int *width, int *height)
    540 {
    541 	int		columns, rows, numPixels;
    542 	byte	*pixbuf;
    543 	int		row, column;
    544 	byte	*buf_p;
    545 	byte	*buffer;
    546 	int		length;
    547 	TargaHeader		targa_header;
    548 	byte			*targa_rgba;
    549 	byte tmp[2];
    550 
    551 	*pic = NULL;
    552 
    553 	//
    554 	// load the file
    555 	//
    556 	length = ri.FS_LoadFile (name, (void **)&buffer);
    557 	if (!buffer)
    558 	{
    559 		ri.Con_Printf (PRINT_DEVELOPER, "Bad tga file %s\n", name);
    560 		return;
    561 	}
    562 
    563 	buf_p = buffer;
    564 
    565 	targa_header.id_length = *buf_p++;
    566 	targa_header.colormap_type = *buf_p++;
    567 	targa_header.image_type = *buf_p++;
    568 	
    569 	tmp[0] = buf_p[0];
    570 	tmp[1] = buf_p[1];
    571 	targa_header.colormap_index = LittleShort ( *((short *)tmp) );
    572 	buf_p+=2;
    573 	tmp[0] = buf_p[0];
    574 	tmp[1] = buf_p[1];
    575 	targa_header.colormap_length = LittleShort ( *((short *)tmp) );
    576 	buf_p+=2;
    577 	targa_header.colormap_size = *buf_p++;
    578 	targa_header.x_origin = LittleShort ( *((short *)buf_p) );
    579 	buf_p+=2;
    580 	targa_header.y_origin = LittleShort ( *((short *)buf_p) );
    581 	buf_p+=2;
    582 	targa_header.width = LittleShort ( *((short *)buf_p) );
    583 	buf_p+=2;
    584 	targa_header.height = LittleShort ( *((short *)buf_p) );
    585 	buf_p+=2;
    586 	targa_header.pixel_size = *buf_p++;
    587 	targa_header.attributes = *buf_p++;
    588 
    589 	if (targa_header.image_type!=2 
    590 		&& targa_header.image_type!=10) 
    591 		ri.Sys_Error (ERR_DROP, "LoadTGA: Only type 2 and 10 targa RGB images supported\n");
    592 
    593 	if (targa_header.colormap_type !=0 
    594 		|| (targa_header.pixel_size!=32 && targa_header.pixel_size!=24))
    595 		ri.Sys_Error (ERR_DROP, "LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
    596 
    597 	columns = targa_header.width;
    598 	rows = targa_header.height;
    599 	numPixels = columns * rows;
    600 
    601 	if (width)
    602 		*width = columns;
    603 	if (height)
    604 		*height = rows;
    605 
    606 	targa_rgba = malloc (numPixels*4);
    607 	*pic = targa_rgba;
    608 
    609 	if (targa_header.id_length != 0)
    610 		buf_p += targa_header.id_length;  // skip TARGA image comment
    611 	
    612 	if (targa_header.image_type==2) {  // Uncompressed, RGB images
    613 		for(row=rows-1; row>=0; row--) {
    614 			pixbuf = targa_rgba + row*columns*4;
    615 			for(column=0; column<columns; column++) {
    616 				unsigned char red,green,blue,alphabyte;
    617 				switch (targa_header.pixel_size) {
    618 					case 24:
    619 							
    620 							blue = *buf_p++;
    621 							green = *buf_p++;
    622 							red = *buf_p++;
    623 							*pixbuf++ = red;
    624 							*pixbuf++ = green;
    625 							*pixbuf++ = blue;
    626 							*pixbuf++ = 255;
    627 							break;
    628 					case 32:
    629 							blue = *buf_p++;
    630 							green = *buf_p++;
    631 							red = *buf_p++;
    632 							alphabyte = *buf_p++;
    633 							*pixbuf++ = red;
    634 							*pixbuf++ = green;
    635 							*pixbuf++ = blue;
    636 							*pixbuf++ = alphabyte;
    637 							break;
    638 				}
    639 			}
    640 		}
    641 	}
    642 	else if (targa_header.image_type==10) {   // Runlength encoded RGB images
    643 		unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
    644 		for(row=rows-1; row>=0; row--) {
    645 			pixbuf = targa_rgba + row*columns*4;
    646 			for(column=0; column<columns; ) {
    647 				packetHeader= *buf_p++;
    648 				packetSize = 1 + (packetHeader & 0x7f);
    649 				if (packetHeader & 0x80) {        // run-length packet
    650 					switch (targa_header.pixel_size) {
    651 						case 24:
    652 								blue = *buf_p++;
    653 								green = *buf_p++;
    654 								red = *buf_p++;
    655 								alphabyte = 255;
    656 								break;
    657 						case 32:
    658 								blue = *buf_p++;
    659 								green = *buf_p++;
    660 								red = *buf_p++;
    661 								alphabyte = *buf_p++;
    662 								break;
    663 					}
    664 	
    665 					for(j=0;j<packetSize;j++) {
    666 						*pixbuf++=red;
    667 						*pixbuf++=green;
    668 						*pixbuf++=blue;
    669 						*pixbuf++=alphabyte;
    670 						column++;
    671 						if (column==columns) { // run spans across rows
    672 							column=0;
    673 							if (row>0)
    674 								row--;
    675 							else
    676 								goto breakOut;
    677 							pixbuf = targa_rgba + row*columns*4;
    678 						}
    679 					}
    680 				}
    681 				else {                            // non run-length packet
    682 					for(j=0;j<packetSize;j++) {
    683 						switch (targa_header.pixel_size) {
    684 							case 24:
    685 									blue = *buf_p++;
    686 									green = *buf_p++;
    687 									red = *buf_p++;
    688 									*pixbuf++ = red;
    689 									*pixbuf++ = green;
    690 									*pixbuf++ = blue;
    691 									*pixbuf++ = 255;
    692 									break;
    693 							case 32:
    694 									blue = *buf_p++;
    695 									green = *buf_p++;
    696 									red = *buf_p++;
    697 									alphabyte = *buf_p++;
    698 									*pixbuf++ = red;
    699 									*pixbuf++ = green;
    700 									*pixbuf++ = blue;
    701 									*pixbuf++ = alphabyte;
    702 									break;
    703 						}
    704 						column++;
    705 						if (column==columns) { // pixel packet run spans across rows
    706 							column=0;
    707 							if (row>0)
    708 								row--;
    709 							else
    710 								goto breakOut;
    711 							pixbuf = targa_rgba + row*columns*4;
    712 						}						
    713 					}
    714 				}
    715 			}
    716 			breakOut:;
    717 		}
    718 	}
    719 
    720 	ri.FS_FreeFile (buffer);
    721 }
    722 
    723 
    724 /*
    725 ====================================================================
    726 
    727 IMAGE FLOOD FILLING
    728 
    729 ====================================================================
    730 */
    731 
    732 
    733 /*
    734 =================
    735 Mod_FloodFillSkin
    736 
    737 Fill background pixels so mipmapping doesn't have haloes
    738 =================
    739 */
    740 
    741 typedef struct
    742 {
    743 	short		x, y;
    744 } floodfill_t;
    745 
    746 // must be a power of 2
    747 #define FLOODFILL_FIFO_SIZE 0x1000
    748 #define FLOODFILL_FIFO_MASK (FLOODFILL_FIFO_SIZE - 1)
    749 
    750 #define FLOODFILL_STEP( off, dx, dy ) \
    751 { \
    752 	if (pos[off] == fillcolor) \
    753 	{ \
    754 		pos[off] = 255; \
    755 		fifo[inpt].x = x + (dx), fifo[inpt].y = y + (dy); \
    756 		inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; \
    757 	} \
    758 	else if (pos[off] != 255) fdc = pos[off]; \
    759 }
    760 
    761 void R_FloodFillSkin( byte *skin, int skinwidth, int skinheight )
    762 {
    763 	byte				fillcolor = *skin; // assume this is the pixel to fill
    764 	floodfill_t			fifo[FLOODFILL_FIFO_SIZE];
    765 	int					inpt = 0, outpt = 0;
    766 	int					filledcolor = -1;
    767 	int					i;
    768 
    769 	if (filledcolor == -1)
    770 	{
    771 		filledcolor = 0;
    772 		// attempt to find opaque black
    773 		for (i = 0; i < 256; ++i)
    774 			if (d_8to24table[i] == (255 << 0)) // alpha 1.0
    775 			{
    776 				filledcolor = i;
    777 				break;
    778 			}
    779 	}
    780 
    781 	// can't fill to filled color or to transparent color (used as visited marker)
    782 	if ((fillcolor == filledcolor) || (fillcolor == 255))
    783 	{
    784 		//printf( "not filling skin from %d to %d\n", fillcolor, filledcolor );
    785 		return;
    786 	}
    787 
    788 	fifo[inpt].x = 0, fifo[inpt].y = 0;
    789 	inpt = (inpt + 1) & FLOODFILL_FIFO_MASK;
    790 
    791 	while (outpt != inpt)
    792 	{
    793 		int			x = fifo[outpt].x, y = fifo[outpt].y;
    794 		int			fdc = filledcolor;
    795 		byte		*pos = &skin[x + skinwidth * y];
    796 
    797 		outpt = (outpt + 1) & FLOODFILL_FIFO_MASK;
    798 
    799 		if (x > 0)				FLOODFILL_STEP( -1, -1, 0 );
    800 		if (x < skinwidth - 1)	FLOODFILL_STEP( 1, 1, 0 );
    801 		if (y > 0)				FLOODFILL_STEP( -skinwidth, 0, -1 );
    802 		if (y < skinheight - 1)	FLOODFILL_STEP( skinwidth, 0, 1 );
    803 		skin[x + skinwidth * y] = fdc;
    804 	}
    805 }
    806 
    807 //=======================================================
    808 
    809 
    810 /*
    811 ================
    812 GL_ResampleTexture
    813 ================
    814 */
    815 void GL_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out,  int outwidth, int outheight)
    816 {
    817 	int		i, j;
    818 	unsigned	*inrow, *inrow2;
    819 	unsigned	frac, fracstep;
    820 	unsigned	p1[1024], p2[1024];
    821 	byte		*pix1, *pix2, *pix3, *pix4;
    822 
    823 	fracstep = inwidth*0x10000/outwidth;
    824 
    825 	frac = fracstep>>2;
    826 	for (i=0 ; i<outwidth ; i++)
    827 	{
    828 		p1[i] = 4*(frac>>16);
    829 		frac += fracstep;
    830 	}
    831 	frac = 3*(fracstep>>2);
    832 	for (i=0 ; i<outwidth ; i++)
    833 	{
    834 		p2[i] = 4*(frac>>16);
    835 		frac += fracstep;
    836 	}
    837 
    838 	for (i=0 ; i<outheight ; i++, out += outwidth)
    839 	{
    840 		inrow = in + inwidth*(int)((i+0.25)*inheight/outheight);
    841 		inrow2 = in + inwidth*(int)((i+0.75)*inheight/outheight);
    842 		frac = fracstep >> 1;
    843 		for (j=0 ; j<outwidth ; j++)
    844 		{
    845 			pix1 = (byte *)inrow + p1[j];
    846 			pix2 = (byte *)inrow + p2[j];
    847 			pix3 = (byte *)inrow2 + p1[j];
    848 			pix4 = (byte *)inrow2 + p2[j];
    849 			((byte *)(out+j))[0] = (pix1[0] + pix2[0] + pix3[0] + pix4[0])>>2;
    850 			((byte *)(out+j))[1] = (pix1[1] + pix2[1] + pix3[1] + pix4[1])>>2;
    851 			((byte *)(out+j))[2] = (pix1[2] + pix2[2] + pix3[2] + pix4[2])>>2;
    852 			((byte *)(out+j))[3] = (pix1[3] + pix2[3] + pix3[3] + pix4[3])>>2;
    853 		}
    854 	}
    855 }
    856 
    857 /*
    858 ================
    859 GL_LightScaleTexture
    860 
    861 Scale up the pixel values in a texture to increase the
    862 lighting range
    863 ================
    864 */
    865 void GL_LightScaleTexture (unsigned *in, int inwidth, int inheight, qboolean only_gamma )
    866 {
    867 	if ( only_gamma )
    868 	{
    869 		int		i, c;
    870 		byte	*p;
    871 
    872 		p = (byte *)in;
    873 
    874 		c = inwidth*inheight;
    875 		for (i=0 ; i<c ; i++, p+=4)
    876 		{
    877 			p[0] = gammatable[p[0]];
    878 			p[1] = gammatable[p[1]];
    879 			p[2] = gammatable[p[2]];
    880 		}
    881 	}
    882 	else
    883 	{
    884 		int		i, c;
    885 		byte	*p;
    886 
    887 		p = (byte *)in;
    888 
    889 		c = inwidth*inheight;
    890 		for (i=0 ; i<c ; i++, p+=4)
    891 		{
    892 			p[0] = gammatable[intensitytable[p[0]]];
    893 			p[1] = gammatable[intensitytable[p[1]]];
    894 			p[2] = gammatable[intensitytable[p[2]]];
    895 		}
    896 	}
    897 }
    898 
    899 /*
    900 ================
    901 GL_MipMap
    902 
    903 Operates in place, quartering the size of the texture
    904 ================
    905 */
    906 void GL_MipMap (byte *in, int width, int height)
    907 {
    908 	int		i, j;
    909 	byte	*out;
    910 
    911 	width <<=2;
    912 	height >>= 1;
    913 	out = in;
    914 	for (i=0 ; i<height ; i++, in+=width)
    915 	{
    916 		for (j=0 ; j<width ; j+=8, out+=4, in+=8)
    917 		{
    918 			out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2;
    919 			out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2;
    920 			out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2;
    921 			out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2;
    922 		}
    923 	}
    924 }
    925 
    926 /*
    927 ===============
    928 GL_Upload32
    929 
    930 Returns has_alpha
    931 ===============
    932 */
    933 void GL_BuildPalettedTexture( unsigned char *paletted_texture, unsigned char *scaled, int scaled_width, int scaled_height )
    934 {
    935 	int i;
    936 
    937 	for ( i = 0; i < scaled_width * scaled_height; i++ )
    938 	{
    939 		unsigned int r, g, b, c;
    940 
    941 		r = ( scaled[0] >> 3 ) & 31;
    942 		g = ( scaled[1] >> 2 ) & 63;
    943 		b = ( scaled[2] >> 3 ) & 31;
    944 
    945 		c = r | ( g << 5 ) | ( b << 11 );
    946 
    947 		paletted_texture[i] = gl_state.d_16to8table[c];
    948 
    949 		scaled += 4;
    950 	}
    951 }
    952 
    953 int		upload_width, upload_height;
    954 qboolean uploaded_paletted;
    955 
    956 qboolean GL_Upload32 (unsigned *data, int width, int height,  qboolean mipmap)
    957 {
    958 	int			samples;
    959 	unsigned	scaled[256*256];
    960 	unsigned char paletted_texture[256*256];
    961 	int			scaled_width, scaled_height;
    962 	int			i, c;
    963 	byte		*scan;
    964 	int comp;
    965 
    966 	uploaded_paletted = false;
    967 
    968 	for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
    969 		;
    970 	if (gl_round_down->value && scaled_width > width && mipmap)
    971 		scaled_width >>= 1;
    972 	for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
    973 		;
    974 	if (gl_round_down->value && scaled_height > height && mipmap)
    975 		scaled_height >>= 1;
    976 
    977 	// let people sample down the world textures for speed
    978 	if (mipmap)
    979 	{
    980 		scaled_width >>= (int)gl_picmip->value;
    981 		scaled_height >>= (int)gl_picmip->value;
    982 	}
    983 
    984 	// don't ever bother with >256 textures
    985 	if (scaled_width > 256)
    986 		scaled_width = 256;
    987 	if (scaled_height > 256)
    988 		scaled_height = 256;
    989 
    990 	if (scaled_width < 1)
    991 		scaled_width = 1;
    992 	if (scaled_height < 1)
    993 		scaled_height = 1;
    994 
    995 	upload_width = scaled_width;
    996 	upload_height = scaled_height;
    997 
    998 	if (scaled_width * scaled_height > sizeof(scaled)/4)
    999 		ri.Sys_Error (ERR_DROP, "GL_Upload32: too big");
   1000 
   1001 	// scan the texture for any non-255 alpha
   1002 	c = width*height;
   1003 	scan = ((byte *)data) + 3;
   1004 	samples = gl_solid_format;
   1005 	for (i=0 ; i<c ; i++, scan += 4)
   1006 	{
   1007 		if ( *scan != 255 )
   1008 		{
   1009 			samples = gl_alpha_format;
   1010 			break;
   1011 		}
   1012 	}
   1013 
   1014 	if (samples == gl_solid_format)
   1015 	    comp = gl_tex_solid_format;
   1016 	else if (samples == gl_alpha_format)
   1017 	    comp = gl_tex_alpha_format;
   1018 	else {
   1019 	    ri.Con_Printf (PRINT_ALL,
   1020 			   "Unknown number of texture components %i\n",
   1021 			   samples);
   1022 	    comp = samples;
   1023 	}
   1024 
   1025 #if 0
   1026 	if (mipmap)
   1027 		gluBuild2DMipmaps (GL_TEXTURE_2D, samples, width, height, GL_RGBA, GL_UNSIGNED_BYTE, trans);
   1028 	else if (scaled_width == width && scaled_height == height)
   1029 		qglTexImage2D (GL_TEXTURE_2D, 0, comp, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
   1030 	else
   1031 	{
   1032 		gluScaleImage (GL_RGBA, width, height, GL_UNSIGNED_BYTE, trans,
   1033 			scaled_width, scaled_height, GL_UNSIGNED_BYTE, scaled);
   1034 		qglTexImage2D (GL_TEXTURE_2D, 0, comp, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
   1035 	}
   1036 #else
   1037 
   1038 	if (scaled_width == width && scaled_height == height)
   1039 	{
   1040 		if (!mipmap)
   1041 		{
   1042 			if ( qglColorTableEXT && gl_ext_palettedtexture->value && samples == gl_solid_format )
   1043 			{
   1044 				uploaded_paletted = true;
   1045 				GL_BuildPalettedTexture( paletted_texture, ( unsigned char * ) data, scaled_width, scaled_height );
   1046 				qglTexImage2D( GL_TEXTURE_2D,
   1047 							  0,
   1048 							  GL_COLOR_INDEX8_EXT,
   1049 							  scaled_width,
   1050 							  scaled_height,
   1051 							  0,
   1052 							  GL_COLOR_INDEX,
   1053 							  GL_UNSIGNED_BYTE,
   1054 							  paletted_texture );
   1055 			}
   1056 			else
   1057 			{
   1058 				qglTexImage2D (GL_TEXTURE_2D, 0, comp, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
   1059 			}
   1060 			goto done;
   1061 		}
   1062 		memcpy (scaled, data, width*height*4);
   1063 	}
   1064 	else
   1065 		GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
   1066 
   1067 	GL_LightScaleTexture (scaled, scaled_width, scaled_height, !mipmap );
   1068 
   1069 	if ( qglColorTableEXT && gl_ext_palettedtexture->value && ( samples == gl_solid_format ) )
   1070 	{
   1071 		uploaded_paletted = true;
   1072 		GL_BuildPalettedTexture( paletted_texture, ( unsigned char * ) scaled, scaled_width, scaled_height );
   1073 		qglTexImage2D( GL_TEXTURE_2D,
   1074 					  0,
   1075 					  GL_COLOR_INDEX8_EXT,
   1076 					  scaled_width,
   1077 					  scaled_height,
   1078 					  0,
   1079 					  GL_COLOR_INDEX,
   1080 					  GL_UNSIGNED_BYTE,
   1081 					  paletted_texture );
   1082 	}
   1083 	else
   1084 	{
   1085 		qglTexImage2D( GL_TEXTURE_2D, 0, comp, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled );
   1086 	}
   1087 
   1088 	if (mipmap)
   1089 	{
   1090 		int		miplevel;
   1091 
   1092 		miplevel = 0;
   1093 		while (scaled_width > 1 || scaled_height > 1)
   1094 		{
   1095 			GL_MipMap ((byte *)scaled, scaled_width, scaled_height);
   1096 			scaled_width >>= 1;
   1097 			scaled_height >>= 1;
   1098 			if (scaled_width < 1)
   1099 				scaled_width = 1;
   1100 			if (scaled_height < 1)
   1101 				scaled_height = 1;
   1102 			miplevel++;
   1103 			if ( qglColorTableEXT && gl_ext_palettedtexture->value && samples == gl_solid_format )
   1104 			{
   1105 				uploaded_paletted = true;
   1106 				GL_BuildPalettedTexture( paletted_texture, ( unsigned char * ) scaled, scaled_width, scaled_height );
   1107 				qglTexImage2D( GL_TEXTURE_2D,
   1108 							  miplevel,
   1109 							  GL_COLOR_INDEX8_EXT,
   1110 							  scaled_width,
   1111 							  scaled_height,
   1112 							  0,
   1113 							  GL_COLOR_INDEX,
   1114 							  GL_UNSIGNED_BYTE,
   1115 							  paletted_texture );
   1116 			}
   1117 			else
   1118 			{
   1119 				qglTexImage2D (GL_TEXTURE_2D, miplevel, comp, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
   1120 			}
   1121 		}
   1122 	}
   1123 done: ;
   1124 #endif
   1125 
   1126 
   1127 	if (mipmap)
   1128 	{
   1129 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
   1130 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
   1131 	}
   1132 	else
   1133 	{
   1134 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
   1135 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
   1136 	}
   1137 
   1138 	return (samples == gl_alpha_format);
   1139 }
   1140 
   1141 /*
   1142 ===============
   1143 GL_Upload8
   1144 
   1145 Returns has_alpha
   1146 ===============
   1147 */
   1148 /*
   1149 static qboolean IsPowerOf2( int value )
   1150 {
   1151 	int i = 1;
   1152 
   1153 
   1154 	while ( 1 )
   1155 	{
   1156 		if ( value == i )
   1157 			return true;
   1158 		if ( i > value )
   1159 			return false;
   1160 		i <<= 1;
   1161 	}
   1162 }
   1163 */
   1164 
   1165 qboolean GL_Upload8 (byte *data, int width, int height,  qboolean mipmap, qboolean is_sky )
   1166 {
   1167 	unsigned	trans[512*256];
   1168 	int			i, s;
   1169 	int			p;
   1170 
   1171 	s = width*height;
   1172 
   1173 	if (s > sizeof(trans)/4)
   1174 		ri.Sys_Error (ERR_DROP, "GL_Upload8: too large");
   1175 
   1176 	if ( qglColorTableEXT && 
   1177 		 gl_ext_palettedtexture->value && 
   1178 		 is_sky )
   1179 	{
   1180 		qglTexImage2D( GL_TEXTURE_2D,
   1181 					  0,
   1182 					  GL_COLOR_INDEX8_EXT,
   1183 					  width,
   1184 					  height,
   1185 					  0,
   1186 					  GL_COLOR_INDEX,
   1187 					  GL_UNSIGNED_BYTE,
   1188 					  data );
   1189 
   1190 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
   1191 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
   1192 	}
   1193 	else
   1194 	{
   1195 		for (i=0 ; i<s ; i++)
   1196 		{
   1197 			p = data[i];
   1198 			trans[i] = d_8to24table[p];
   1199 
   1200 			if (p == 255)
   1201 			{	// transparent, so scan around for another color
   1202 				// to avoid alpha fringes
   1203 				// FIXME: do a full flood fill so mips work...
   1204 				if (i > width && data[i-width] != 255)
   1205 					p = data[i-width];
   1206 				else if (i < s-width && data[i+width] != 255)
   1207 					p = data[i+width];
   1208 				else if (i > 0 && data[i-1] != 255)
   1209 					p = data[i-1];
   1210 				else if (i < s-1 && data[i+1] != 255)
   1211 					p = data[i+1];
   1212 				else
   1213 					p = 0;
   1214 				// copy rgb components
   1215 				((byte *)&trans[i])[0] = ((byte *)&d_8to24table[p])[0];
   1216 				((byte *)&trans[i])[1] = ((byte *)&d_8to24table[p])[1];
   1217 				((byte *)&trans[i])[2] = ((byte *)&d_8to24table[p])[2];
   1218 			}
   1219 		}
   1220 
   1221 		return GL_Upload32 (trans, width, height, mipmap);
   1222 	}
   1223 }
   1224 
   1225 
   1226 /*
   1227 ================
   1228 GL_LoadPic
   1229 
   1230 This is also used as an entry point for the generated r_notexture
   1231 ================
   1232 */
   1233 image_t *GL_LoadPic (char *name, byte *pic, int width, int height, imagetype_t type, int bits)
   1234 {
   1235 	image_t		*image;
   1236 	int			i;
   1237 
   1238 	// find a free image_t
   1239 	for (i=0, image=gltextures ; i<numgltextures ; i++,image++)
   1240 	{
   1241 		if (!image->texnum)
   1242 			break;
   1243 	}
   1244 	if (i == numgltextures)
   1245 	{
   1246 		if (numgltextures == MAX_GLTEXTURES)
   1247 			ri.Sys_Error (ERR_DROP, "MAX_GLTEXTURES");
   1248 		numgltextures++;
   1249 	}
   1250 	image = &gltextures[i];
   1251 
   1252 	if (strlen(name) >= sizeof(image->name))
   1253 		ri.Sys_Error (ERR_DROP, "Draw_LoadPic: \"%s\" is too long", name);
   1254 	strcpy (image->name, name);
   1255 	image->registration_sequence = registration_sequence;
   1256 
   1257 	image->width = width;
   1258 	image->height = height;
   1259 	image->type = type;
   1260 
   1261 	if (type == it_skin && bits == 8)
   1262 		R_FloodFillSkin(pic, width, height);
   1263 
   1264 	// load little pics into the scrap
   1265 	if (image->type == it_pic && bits == 8
   1266 		&& image->width < 64 && image->height < 64)
   1267 	{
   1268 		int		x, y;
   1269 		int		i, j, k;
   1270 		int		texnum;
   1271 
   1272 		texnum = Scrap_AllocBlock (image->width, image->height, &x, &y);
   1273 		if (texnum == -1)
   1274 			goto nonscrap;
   1275 		scrap_dirty = true;
   1276 
   1277 		// copy the texels into the scrap block
   1278 		k = 0;
   1279 		for (i=0 ; i<image->height ; i++)
   1280 			for (j=0 ; j<image->width ; j++, k++)
   1281 				scrap_texels[texnum][(y+i)*BLOCK_WIDTH + x + j] = pic[k];
   1282 		image->texnum = TEXNUM_SCRAPS + texnum;
   1283 		image->scrap = true;
   1284 		image->has_alpha = true;
   1285 		image->sl = (x+0.01)/(float)BLOCK_WIDTH;
   1286 		image->sh = (x+image->width-0.01)/(float)BLOCK_WIDTH;
   1287 		image->tl = (y+0.01)/(float)BLOCK_WIDTH;
   1288 		image->th = (y+image->height-0.01)/(float)BLOCK_WIDTH;
   1289 	}
   1290 	else
   1291 	{
   1292 nonscrap:
   1293 		image->scrap = false;
   1294 		image->texnum = TEXNUM_IMAGES + (image - gltextures);
   1295 		GL_Bind(image->texnum);
   1296 		if (bits == 8)
   1297 			image->has_alpha = GL_Upload8 (pic, width, height, (image->type != it_pic && image->type != it_sky), image->type == it_sky );
   1298 		else
   1299 			image->has_alpha = GL_Upload32 ((unsigned *)pic, width, height, (image->type != it_pic && image->type != it_sky) );
   1300 		image->upload_width = upload_width;		// after power of 2 and scales
   1301 		image->upload_height = upload_height;
   1302 		image->paletted = uploaded_paletted;
   1303 		image->sl = 0;
   1304 		image->sh = 1;
   1305 		image->tl = 0;
   1306 		image->th = 1;
   1307 	}
   1308 
   1309 	return image;
   1310 }
   1311 
   1312 
   1313 /*
   1314 ================
   1315 GL_LoadWal
   1316 ================
   1317 */
   1318 image_t *GL_LoadWal (char *name)
   1319 {
   1320 	miptex_t	*mt;
   1321 	int			width, height, ofs;
   1322 	image_t		*image;
   1323 
   1324 	ri.FS_LoadFile (name, (void **)&mt);
   1325 	if (!mt)
   1326 	{
   1327 		ri.Con_Printf (PRINT_ALL, "GL_FindImage: can't load %s\n", name);
   1328 		return r_notexture;
   1329 	}
   1330 
   1331 	width = LittleLong (mt->width);
   1332 	height = LittleLong (mt->height);
   1333 	ofs = LittleLong (mt->offsets[0]);
   1334 
   1335 	image = GL_LoadPic (name, (byte *)mt + ofs, width, height, it_wall, 8);
   1336 
   1337 	ri.FS_FreeFile ((void *)mt);
   1338 
   1339 	return image;
   1340 }
   1341 
   1342 /*
   1343 ===============
   1344 GL_FindImage
   1345 
   1346 Finds or loads the given image
   1347 ===============
   1348 */
   1349 image_t	*GL_FindImage (char *name, imagetype_t type)
   1350 {
   1351 	image_t	*image;
   1352 	int		i, len;
   1353 	byte	*pic, *palette;
   1354 	int		width, height;
   1355 
   1356 	if (!name)
   1357 		return NULL;	//	ri.Sys_Error (ERR_DROP, "GL_FindImage: NULL name");
   1358 	len = strlen(name);
   1359 	if (len<5)
   1360 		return NULL;	//	ri.Sys_Error (ERR_DROP, "GL_FindImage: bad name: %s", name);
   1361 
   1362 	// look for it
   1363 	for (i=0, image=gltextures ; i<numgltextures ; i++,image++)
   1364 	{
   1365 		if (!strcmp(name, image->name))
   1366 		{
   1367 			image->registration_sequence = registration_sequence;
   1368 			return image;
   1369 		}
   1370 	}
   1371 
   1372 	//
   1373 	// load the pic from disk
   1374 	//
   1375 	pic = NULL;
   1376 	palette = NULL;
   1377 	if (!strcmp(name+len-4, ".pcx"))
   1378 	{
   1379 		LoadPCX (name, &pic, &palette, &width, &height);
   1380 		if (!pic)
   1381 			return NULL; // ri.Sys_Error (ERR_DROP, "GL_FindImage: can't load %s", name);
   1382 		image = GL_LoadPic (name, pic, width, height, type, 8);
   1383 	}
   1384 	else if (!strcmp(name+len-4, ".wal"))
   1385 	{
   1386 		image = GL_LoadWal (name);
   1387 	}
   1388 	else if (!strcmp(name+len-4, ".tga"))
   1389 	{
   1390 		LoadTGA (name, &pic, &width, &height);
   1391 		if (!pic)
   1392 			return NULL; // ri.Sys_Error (ERR_DROP, "GL_FindImage: can't load %s", name);
   1393 		image = GL_LoadPic (name, pic, width, height, type, 32);
   1394 	}
   1395 	else
   1396 		return NULL;	//	ri.Sys_Error (ERR_DROP, "GL_FindImage: bad extension on: %s", name);
   1397 
   1398 
   1399 	if (pic)
   1400 		free(pic);
   1401 	if (palette)
   1402 		free(palette);
   1403 
   1404 	return image;
   1405 }
   1406 
   1407 
   1408 
   1409 /*
   1410 ===============
   1411 R_RegisterSkin
   1412 ===============
   1413 */
   1414 struct image_s *R_RegisterSkin (char *name)
   1415 {
   1416 	return GL_FindImage (name, it_skin);
   1417 }
   1418 
   1419 
   1420 /*
   1421 ================
   1422 GL_FreeUnusedImages
   1423 
   1424 Any image that was not touched on this registration sequence
   1425 will be freed.
   1426 ================
   1427 */
   1428 void GL_FreeUnusedImages (void)
   1429 {
   1430 	int		i;
   1431 	image_t	*image;
   1432 
   1433 	// never free r_notexture or particle texture
   1434 	r_notexture->registration_sequence = registration_sequence;
   1435 	r_particletexture->registration_sequence = registration_sequence;
   1436 
   1437 	for (i=0, image=gltextures ; i<numgltextures ; i++, image++)
   1438 	{
   1439 		if (image->registration_sequence == registration_sequence)
   1440 			continue;		// used this sequence
   1441 		if (!image->registration_sequence)
   1442 			continue;		// free image_t slot
   1443 		if (image->type == it_pic)
   1444 			continue;		// don't free pics
   1445 		// free it
   1446 		qglDeleteTextures (1, &image->texnum);
   1447 		memset (image, 0, sizeof(*image));
   1448 	}
   1449 }
   1450 
   1451 
   1452 /*
   1453 ===============
   1454 Draw_GetPalette
   1455 ===============
   1456 */
   1457 int Draw_GetPalette (void)
   1458 {
   1459 	int		i;
   1460 	int		r, g, b;
   1461 	unsigned	v;
   1462 	byte	*pic, *pal;
   1463 	int		width, height;
   1464 
   1465 	// get the palette
   1466 
   1467 	LoadPCX ("pics/colormap.pcx", &pic, &pal, &width, &height);
   1468 	if (!pal)
   1469 		ri.Sys_Error (ERR_FATAL, "Couldn't load pics/colormap.pcx");
   1470 
   1471 	for (i=0 ; i<256 ; i++)
   1472 	{
   1473 		r = pal[i*3+0];
   1474 		g = pal[i*3+1];
   1475 		b = pal[i*3+2];
   1476 		
   1477 		v = (255<<24) + (r<<0) + (g<<8) + (b<<16);
   1478 		d_8to24table[i] = LittleLong(v);
   1479 	}
   1480 
   1481 	d_8to24table[255] &= LittleLong(0xffffff);	// 255 is transparent
   1482 
   1483 	free (pic);
   1484 	free (pal);
   1485 
   1486 	return 0;
   1487 }
   1488 
   1489 
   1490 /*
   1491 ===============
   1492 GL_InitImages
   1493 ===============
   1494 */
   1495 void	GL_InitImages (void)
   1496 {
   1497 	int		i, j;
   1498 	float	g = vid_gamma->value;
   1499 
   1500 	registration_sequence = 1;
   1501 
   1502 	// init intensity conversions
   1503 	intensity = ri.Cvar_Get ("intensity", "2", 0);
   1504 
   1505 	if ( intensity->value <= 1 )
   1506 		ri.Cvar_Set( "intensity", "1" );
   1507 
   1508 	gl_state.inverse_intensity = 1 / intensity->value;
   1509 
   1510 	Draw_GetPalette ();
   1511 
   1512 	if ( qglColorTableEXT )
   1513 	{
   1514 		ri.FS_LoadFile( "pics/16to8.dat", &gl_state.d_16to8table );
   1515 		if ( !gl_state.d_16to8table )
   1516 			ri.Sys_Error( ERR_FATAL, "Couldn't load pics/16to8.pcx");
   1517 	}
   1518 
   1519 	if ( gl_config.renderer & ( GL_RENDERER_VOODOO | GL_RENDERER_VOODOO2 ) )
   1520 	{
   1521 		g = 1.0F;
   1522 	}
   1523 
   1524 	for ( i = 0; i < 256; i++ )
   1525 	{
   1526 		if ( g == 1 )
   1527 		{
   1528 			gammatable[i] = i;
   1529 		}
   1530 		else
   1531 		{
   1532 			float inf;
   1533 
   1534 			inf = 255 * pow ( (i+0.5)/255.5 , g ) + 0.5;
   1535 			if (inf < 0)
   1536 				inf = 0;
   1537 			if (inf > 255)
   1538 				inf = 255;
   1539 			gammatable[i] = inf;
   1540 		}
   1541 	}
   1542 
   1543 	for (i=0 ; i<256 ; i++)
   1544 	{
   1545 		j = i*intensity->value;
   1546 		if (j > 255)
   1547 			j = 255;
   1548 		intensitytable[i] = j;
   1549 	}
   1550 }
   1551 
   1552 /*
   1553 ===============
   1554 GL_ShutdownImages
   1555 ===============
   1556 */
   1557 void	GL_ShutdownImages (void)
   1558 {
   1559 	int		i;
   1560 	image_t	*image;
   1561 
   1562 	for (i=0, image=gltextures ; i<numgltextures ; i++, image++)
   1563 	{
   1564 		if (!image->registration_sequence)
   1565 			continue;		// free image_t slot
   1566 		// free it
   1567 		qglDeleteTextures (1, &image->texnum);
   1568 		memset (image, 0, sizeof(*image));
   1569 	}
   1570 }
   1571