1 /*
2  * Copyright (C) 1997-2001 Id Software, Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify it under
5  * the terms of the GNU General Public License as published by the Free
6  * Software Foundation; either version 2 of the License, or (at your option)
7  * any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * 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 along with
16  * this program; if not, write to the Free Software Foundation, Inc., 59
17  * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  */
20 
21 #include "gl_local.h"
22 
23 #include "gl_refl.h"		/* MPO */
24 
25 image_t		gltextures[MAX_GLTEXTURES];
26 int		numgltextures;
27 int		base_textureid;		/* gltextures[i] = base_textureid+i */
28 
29 static byte	intensitytable[256];
30 static unsigned char gammatable[256];
31 
32 cvar_t         *intensity;
33 
34 unsigned	d_8to24table[256];
35 
36 #ifndef QMAX
37 float		d_8to24tablef[256][3];
38 #endif
39 
40 qboolean	GL_Upload8(byte * data, int width, int height, qboolean mipmap, qboolean is_sky);
41 qboolean	GL_Upload32(unsigned *data, int width, int height, qboolean mipmap);
42 
43 
44 int		gl_solid_format = 3;
45 int		gl_alpha_format = 4;
46 
47 int		gl_tex_solid_format = 3;
48 int		gl_tex_alpha_format = 4;
49 
50 int		gl_filter_min = GL_LINEAR_MIPMAP_NEAREST;
51 int		gl_filter_max = GL_LINEAR;
52 
53 void
GL_SetTexturePalette(unsigned palette[256])54 GL_SetTexturePalette(unsigned palette[256])
55 {
56 	int		i;
57 	unsigned char	temptable[768];
58 
59 	if (qglColorTableEXT) {
60 		for (i = 0; i < 256; i++) {
61 			temptable[i * 3 + 0] = (palette[i] >> 0) & 0xff;
62 			temptable[i * 3 + 1] = (palette[i] >> 8) & 0xff;
63 			temptable[i * 3 + 2] = (palette[i] >> 16) & 0xff;
64 		}
65 
66 		qglColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT,
67 		    GL_RGB,
68 		    256,
69 		    GL_RGB,
70 		    GL_UNSIGNED_BYTE,
71 		    temptable);
72 	}
73 }
74 
75 /* Knightmare- added some of Psychospaz's shortcuts */
76 GLenum		bFunc1 = -1;
77 GLenum		bFunc2 = -1;
78 void
GL_BlendFunction(GLenum sfactor,GLenum dfactor)79 GL_BlendFunction(GLenum sfactor, GLenum dfactor)
80 {
81 	if (sfactor != bFunc1 || dfactor != bFunc2) {
82 		bFunc1 = sfactor;
83 		bFunc2 = dfactor;
84 
85 		qglBlendFunc(bFunc1, bFunc2);
86 	}
87 }
88 
89 GLenum		shadeModelMode = -1;
90 
91 void
GL_ShadeModel(GLenum mode)92 GL_ShadeModel(GLenum mode)
93 {
94 	if (mode != shadeModelMode) {
95 		shadeModelMode = mode;
96 		qglShadeModel(mode);
97 	}
98 }
99 
100 void
GL_EnableMultitexture(qboolean enable)101 GL_EnableMultitexture(qboolean enable)
102 {
103 	if (!qglSelectTextureSGIS && !qglActiveTextureARB)
104 		return;
105 
106 	if (enable) {
107 		GL_SelectTexture(GL_TEXTURE1);
108 		qglEnable(GL_TEXTURE_2D);
109 		GL_TexEnv(GL_REPLACE);
110 	} else {
111 		GL_SelectTexture(GL_TEXTURE1);
112 		qglDisable(GL_TEXTURE_2D);
113 		GL_TexEnv(GL_REPLACE);
114 	}
115 
116 	GL_SelectTexture(GL_TEXTURE0);
117 	GL_TexEnv(GL_REPLACE);
118 }
119 
120 void
GL_Enable3dTextureUnit(qboolean enable)121 GL_Enable3dTextureUnit(qboolean enable)
122 {
123 	if (!qglSelectTextureSGIS && !qglActiveTextureARB)
124 		return;
125 
126 	if (enable) {
127 		GL_SelectTexture(GL_TEXTURE2);
128 		qglEnable(GL_TEXTURE_2D);
129 		GL_TexEnv(GL_REPLACE);
130 	} else {
131 		GL_SelectTexture(GL_TEXTURE2);
132 		qglDisable(GL_TEXTURE_2D);
133 		GL_TexEnv(GL_REPLACE);
134 	}
135 
136 	GL_SelectTexture(GL_TEXTURE0);
137 }
138 
139 void
GL_SelectTexture(GLenum texture)140 GL_SelectTexture(GLenum texture)
141 {
142 
143 	int		tmu;
144 
145 	if (!qglSelectTextureSGIS && !qglActiveTextureARB) {
146 		return;
147 	}
148 	if
149 	    (texture == GL_TEXTURE0)
150 		tmu = 0;
151 	else if
152 	    (texture == GL_TEXTURE1)
153 		tmu = 1;
154 	else
155 		tmu = 2;
156 
157 	if (tmu == gl_state.currenttmu)
158 		return;
159 
160 	gl_state.currenttmu = tmu;
161 
162 	if (qglSelectTextureSGIS) {
163 		qglSelectTextureSGIS(texture);
164 	} else if (qglActiveTextureARB) {
165 		qglActiveTextureARB(texture);
166 		qglClientActiveTextureARB(texture);
167 	}
168 }
169 
170 void
GL_TexEnv(GLenum mode)171 GL_TexEnv(GLenum mode)
172 {
173 	static int	lastmodes[2] = {-1, -1};
174 
175 	if (mode != lastmodes[gl_state.currenttmu]) {
176 		qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode);
177 		lastmodes[gl_state.currenttmu] = mode;
178 	}
179 }
180 
181 void
GL_Bind(int texnum)182 GL_Bind(int texnum)
183 {
184 	extern image_t *draw_chars;
185 
186 	if (gl_nobind->value && draw_chars)	/* performance evaluation option */
187 		texnum = draw_chars->texnum;
188 	if (gl_state.currenttextures[gl_state.currenttmu] == texnum)
189 		return;
190 
191 	gl_state.currenttextures[gl_state.currenttmu] = texnum;
192 	qglBindTexture(GL_TEXTURE_2D, texnum);
193 }
194 
195 void
GL_MBind(GLenum target,int texnum)196 GL_MBind(GLenum target, int texnum)
197 {
198 
199 	GL_SelectTexture(target);
200 
201 	if (target == GL_TEXTURE0) {
202 		if (gl_state.currenttextures[0] == texnum)
203 			return;
204 	} else if (target == GL_TEXTURE1) {
205 		if (gl_state.currenttextures[1] == texnum)
206 			return;
207 	} else {
208 		if (gl_state.currenttextures[2] == texnum)
209 			return;
210 	}
211 
212 	GL_Bind(texnum);
213 }
214 
215 typedef struct {
216 	char           *name;
217 	int		minimize, maximize;
218 } glmode_t;
219 
220 glmode_t	modes[] = {
221 	{"GL_NEAREST", GL_NEAREST, GL_NEAREST},
222 	{"GL_LINEAR", GL_LINEAR, GL_LINEAR},
223 	{"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
224 	{"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
225 	{"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
226 	{"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
227 };
228 
229 #define NUM_GL_MODES (sizeof(modes) / sizeof (glmode_t))
230 
231 typedef struct {
232 	char           *name;
233 	int		mode;
234 } gltmode_t;
235 
236 gltmode_t	gl_alpha_modes[] = {
237 	{"default", 4},
238 	{"GL_RGBA", GL_RGBA},
239 	{"GL_RGBA8", GL_RGBA8},
240 	{"GL_RGB5_A1", GL_RGB5_A1},
241 	{"GL_RGBA4", GL_RGBA4},
242 	{"GL_RGBA2", GL_RGBA2},
243 };
244 
245 #define NUM_GL_ALPHA_MODES (sizeof(gl_alpha_modes) / sizeof (gltmode_t))
246 
247 gltmode_t	gl_solid_modes[] = {
248 	{"default", 3},
249 	{"GL_RGB", GL_RGB},
250 	{"GL_RGB8", GL_RGB8},
251 	{"GL_RGB5", GL_RGB5},
252 	{"GL_RGB4", GL_RGB4},
253 	{"GL_R3_G3_B2", GL_R3_G3_B2},
254 #ifdef GL_RGB2_EXT
255 	{"GL_RGB2", GL_RGB2_EXT},
256 #endif
257 };
258 
259 #define NUM_GL_SOLID_MODES (sizeof(gl_solid_modes) / sizeof (gltmode_t))
260 
261 /*
262  * =============== GL_TextureMode ===============
263  */
264 void
GL_TextureMode(char * string)265 GL_TextureMode(char *string)
266 {
267 	int		i;
268 	image_t        *glt;
269 
270 	for (i = 0; i < NUM_GL_MODES; i++) {
271 		if (!Q_stricmp(modes[i].name, string))
272 			break;
273 	}
274 
275 	if (i == NUM_GL_MODES) {
276 		ri.Con_Printf(PRINT_ALL, "bad filter name\n");
277 		return;
278 	}
279 	gl_filter_min = modes[i].minimize;
280 	gl_filter_max = modes[i].maximize;
281 	/* anisotropic */
282 	/* clamp selected anisotropy */
283 	if (gl_config.anisotropic) {
284 		if (gl_anisotropic->value > gl_config.max_anisotropy)
285 			ri.Cvar_SetValue("gl_anisotropic", gl_config.max_anisotropy);
286 		else if (gl_anisotropic->value < 1.0)
287 			ri.Cvar_SetValue("gl_anisotropic", 1.0);
288 	}
289 	/* change all the existing mipmap texture objects */
290 	for (i = 0, glt = gltextures; i < numgltextures; i++, glt++) {
291 		if (glt->type != it_pic && glt->type != it_sky && glt->type != it_part) {
292 			GL_Bind(glt->texnum);
293 			qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
294 			qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
295 			/* anisotropic */
296 			/* Set anisotropic filter if supported and enabled */
297 			if (gl_config.anisotropic && gl_anisotropic->value) {
298 				qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_anisotropic->value);
299 				/* GLfloat largest_supported_anisotropy; */
300 				/* qglGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_ EXT,
301 				   &largest_supported_anisotropy); */
302 				/* qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
303 				   largest_supported_anisotropy); */
304 			}
305 		}
306 	}
307 }
308 
309 
310 /*
311  * =============== GL_TextureAlphaMode ===============
312  */
313 void
GL_TextureAlphaMode(char * string)314 GL_TextureAlphaMode(char *string)
315 {
316 	int		i;
317 
318 	for (i = 0; i < NUM_GL_ALPHA_MODES; i++) {
319 		if (!Q_stricmp(gl_alpha_modes[i].name, string))
320 			break;
321 	}
322 
323 	if (i == NUM_GL_ALPHA_MODES) {
324 		ri.Con_Printf(PRINT_ALL, "bad alpha texture mode name\n");
325 		return;
326 	}
327 	gl_tex_alpha_format = gl_alpha_modes[i].mode;
328 }
329 
330 /*
331  * =============== GL_TextureSolidMode ===============
332  */
333 void
GL_TextureSolidMode(char * string)334 GL_TextureSolidMode(char *string)
335 {
336 	int		i;
337 
338 	for (i = 0; i < NUM_GL_SOLID_MODES; i++) {
339 		if (!Q_stricmp(gl_solid_modes[i].name, string))
340 			break;
341 	}
342 
343 	if (i == NUM_GL_SOLID_MODES) {
344 		ri.Con_Printf(PRINT_ALL, "bad solid texture mode name\n");
345 		return;
346 	}
347 	gl_tex_solid_format = gl_solid_modes[i].mode;
348 }
349 
350 /*
351  * =============== GL_ImageList_f ===============
352  */
353 void
GL_ImageList_f(void)354 GL_ImageList_f(void)
355 {
356 	int		i;
357 	image_t        *image;
358 	int		texels;
359 	const char     *palstrings[2] = {
360 		"RGB",
361 		"PAL"
362 	};
363 
364 	ri.Con_Printf(PRINT_ALL, "------------------\n");
365 	texels = 0;
366 
367 	for (i = 0, image = gltextures; i < numgltextures; i++, image++) {
368 		if (image->texnum <= 0)
369 			continue;
370 		texels += image->upload_width * image->upload_height;
371 		switch (image->type) {
372 		case it_skin:
373 			ri.Con_Printf(PRINT_ALL, "M");
374 			break;
375 		case it_sprite:
376 			ri.Con_Printf(PRINT_ALL, "S");
377 			break;
378 		case it_wall:
379 			ri.Con_Printf(PRINT_ALL, "W");
380 			break;
381 		case it_pic:
382 			ri.Con_Printf(PRINT_ALL, "P");
383 			break;
384 		default:
385 			ri.Con_Printf(PRINT_ALL, " ");
386 			break;
387 		}
388 
389 		ri.Con_Printf(PRINT_ALL, " %3i %3i %s: %s\n",
390 		    image->upload_width, image->upload_height, palstrings[image->paletted], image->name);
391 	}
392 	ri.Con_Printf(PRINT_ALL, "Total texel count (not counting mipmaps): %i\n", texels);
393 }
394 
395 
396 /*
397  *
398  * ============================================================================
399  * =
400  *
401  * scrap allocation
402  *
403  * Allocate all the little status bar obejcts into a single texture to crutch up
404  * inefficient hardware / drivers
405  *
406  * =============================================================================
407  */
408 
409 #define	MAX_SCRAPS		1
410 #define	BLOCK_WIDTH		256
411 #define	BLOCK_HEIGHT		256
412 #define	IMAGERESMAX		1024
413 
414 int		scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH];
415 byte		scrap_texels[MAX_SCRAPS][BLOCK_WIDTH * BLOCK_HEIGHT];
416 qboolean	scrap_dirty;
417 
418 /* returns a texture number and the position inside it */
419 int
Scrap_AllocBlock(int w,int h,int * x,int * y)420 Scrap_AllocBlock(int w, int h, int *x, int *y)
421 {
422 	int		i, j;
423 	int		best, best2;
424 	int		texnum;
425 
426 	for (texnum = 0; texnum < MAX_SCRAPS; texnum++) {
427 		best = BLOCK_HEIGHT;
428 
429 		for (i = 0; i < BLOCK_WIDTH - w; i++) {
430 			best2 = 0;
431 
432 			for (j = 0; j < w; j++) {
433 				if (scrap_allocated[texnum][i + j] >= best)
434 					break;
435 				if (scrap_allocated[texnum][i + j] > best2)
436 					best2 = scrap_allocated[texnum][i + j];
437 			}
438 			if (j == w) {	/* this is a valid spot */
439 				*x = i;
440 				*y = best = best2;
441 			}
442 		}
443 
444 		if (best + h > BLOCK_HEIGHT)
445 			continue;
446 
447 		for (i = 0; i < w; i++)
448 			scrap_allocated[texnum][*x + i] = best + h;
449 
450 		return texnum;
451 	}
452 
453 	return -1;
454 	/* Sys_Error ("Scrap_AllocBlock: full"); */
455 }
456 
457 int		scrap_uploads;
458 
459 void
Scrap_Upload(void)460 Scrap_Upload(void)
461 {
462 	scrap_uploads++;
463 	GL_Bind(TEXNUM_SCRAPS);
464 	GL_Upload8(scrap_texels[0], BLOCK_WIDTH, BLOCK_HEIGHT, false, false);
465 	scrap_dirty = false;
466 }
467 
468 /*
469  * =================================================================
470  *
471  * PCX LOADING
472  *
473  * =================================================================
474  */
475 
476 
477 /*
478  * ============== LoadPCX ==============
479  */
480 void
LoadPCX(char * filename,byte ** pic,byte ** palette,int * width,int * height)481 LoadPCX(char *filename, byte ** pic, byte ** palette, int *width, int *height)
482 {
483 	byte           *raw;
484 	pcx_t          *pcx;
485 	int		x, y;
486 	int		len;
487 	int		dataByte, runLength;
488 	byte           *out, *pix;
489 
490 	*pic = NULL;
491 	*palette = NULL;
492 
493 	/* load the file */
494 	len = ri.FS_LoadFile(filename, (void **)&raw);
495 	if (!raw) {
496 		ri.Con_Printf(PRINT_DEVELOPER, "Bad pcx file %s\n", filename);
497 		return;
498 	}
499 
500 	/* parse the PCX file */
501 	pcx = (pcx_t *) raw;
502 	pcx->xmin = LittleShort(pcx->xmin);
503 	pcx->ymin = LittleShort(pcx->ymin);
504 	pcx->xmax = LittleShort(pcx->xmax);
505 	pcx->ymax = LittleShort(pcx->ymax);
506 	pcx->hres = LittleShort(pcx->hres);
507 	pcx->vres = LittleShort(pcx->vres);
508 	pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
509 	pcx->palette_type = LittleShort(pcx->palette_type);
510 
511 	raw = &pcx->data;
512 
513 	if (pcx->manufacturer != 0x0a
514 	    || pcx->version != 5
515 	    || pcx->encoding != 1
516 	    || pcx->bits_per_pixel != 8
517 	    || pcx->xmax >= 640
518 	    || pcx->ymax >= 480) {
519 		ri.Con_Printf(PRINT_ALL, "Bad pcx file %s\n", filename);
520 		return;
521 	}
522 	out = malloc((pcx->ymax + 1) * (pcx->xmax + 1));
523 
524 	*pic = out;
525 
526 	pix = out;
527 
528 	if (palette) {
529 		*palette = malloc(768);
530 		memcpy(*palette, (byte *) pcx + len - 768, 768);
531 	}
532 	if (width)
533 		*width = pcx->xmax + 1;
534 	if (height)
535 		*height = pcx->ymax + 1;
536 
537 	for (y = 0; y <= pcx->ymax; y++, pix += pcx->xmax + 1) {
538 		for (x = 0; x <= pcx->xmax;) {
539 			dataByte = *raw++;
540 
541 			if ((dataByte & 0xC0) == 0xC0) {
542 				runLength = dataByte & 0x3F;
543 				dataByte = *raw++;
544 			} else
545 				runLength = 1;
546 
547 			while (runLength-- > 0)
548 				pix[x++] = dataByte;
549 		}
550 
551 	}
552 
553 	if (raw - (byte *) pcx > len) {
554 		ri.Con_Printf(PRINT_DEVELOPER, "PCX file %s was malformed", filename);
555 		free(*pic);
556 		*pic = NULL;
557 	}
558 	ri.FS_FreeFile(pcx);
559 }
560 
561 /*
562  * =========================================================
563  *
564  * TARGA LOADING
565  *
566  * =========================================================
567  */
568 
569 typedef struct _TargaHeader {
570 	unsigned char	id_length, colormap_type, image_type;
571 	unsigned short	colormap_index, colormap_length;
572 	unsigned char	colormap_size;
573 	unsigned short	x_origin, y_origin, width, height;
574 	unsigned char	pixel_size, attributes;
575 } TargaHeader;
576 
577 
578 /*
579  * ============= LoadTGA =============
580  */
581 /* Definitions for image types */
582 #define TGA_Null		0	/* no image data */
583 #define TGA_Map			1	/* Uncompressed, color-mapped images */
584 #define TGA_RGB			2	/* Uncompressed, RGB images */
585 #define TGA_Mono		3	/* Uncompressed, black and white images */
586 #define TGA_RLEMap		9	/* Runlength encoded color-mapped images */
587 #define TGA_RLERGB		10	/* Runlength encoded RGB images */
588 #define TGA_RLEMono		11	/* Compressed, black and white images */
589 #define TGA_CompMap		32	/* Compressed color-mapped data, using Huffman, Delta, and runlength encoding */
590 #define TGA_CompMap4		33	/* 4-pass quadtree-type process */
591 /* Definitions for interleave flag */
592 #define TGA_IL_None		0	/* non-interleaved */
593 #define TGA_IL_Two		1	/* two-way (even/odd) interleaving */
594 #define TGA_IL_Four		2	/* four way interleaving */
595 #define TGA_IL_Reserved		3	/* reserved */
596 /* Definitions for origin flag */
597 #define TGA_O_UPPER		0	/* Origin in lower left-hand corner */
598 #define TGA_O_LOWER		1	/* Origin in upper left-hand corner */
599 #define MAXCOLORS 		16384
600 
601 /*
602  * ============= LoadTGA NiceAss: LoadTGA() from Q2Ice, it supports more
603  * formats =============
604  */
605 void
LoadTGA(char * filename,byte ** pic,int * width,int * height)606 LoadTGA(char *filename, byte ** pic, int *width, int *height)
607 {
608 	int		w, h, x, y, i, temp1, temp2;
609 	int		realrow, truerow, baserow, size, interleave, origin;
610 	int		pixel_size, map_idx, mapped, rlencoded, RLE_count, RLE_flag;
611 	TargaHeader	header;
612 	byte		tmp[2], r, g, b, a, j, k, l;
613 	byte           *dst, *ColorMap, *data, *pdata;
614 
615 	/* load file */
616 	ri.FS_LoadFile(filename, (void **)&data);
617 
618 	if (!data)
619 		return;
620 
621 	pdata = data;
622 
623 	header.id_length = *pdata++;
624 	header.colormap_type = *pdata++;
625 	header.image_type = *pdata++;
626 
627 	tmp[0] = pdata[0];
628 	tmp[1] = pdata[1];
629 	header.colormap_index = LittleShort(*((short *)tmp));
630 	pdata += 2;
631 	tmp[0] = pdata[0];
632 	tmp[1] = pdata[1];
633 	header.colormap_length = LittleShort(*((short *)tmp));
634 	pdata += 2;
635 	header.colormap_size = *pdata++;
636 	header.x_origin = LittleShort(*((short *)pdata));
637 	pdata += 2;
638 	header.y_origin = LittleShort(*((short *)pdata));
639 	pdata += 2;
640 	header.width = LittleShort(*((short *)pdata));
641 	pdata += 2;
642 	header.height = LittleShort(*((short *)pdata));
643 	pdata += 2;
644 	header.pixel_size = *pdata++;
645 	header.attributes = *pdata++;
646 
647 	if (header.id_length)
648 		pdata += header.id_length;
649 
650 	/* validate TGA type */
651 	switch (header.image_type) {
652 	case TGA_Map:
653 	case TGA_RGB:
654 	case TGA_Mono:
655 	case TGA_RLEMap:
656 	case TGA_RLERGB:
657 	case TGA_RLEMono:
658 		break;
659 	default:
660 		ri.Sys_Error(ERR_DROP, "LoadTGA: Only type 1 (map), 2 (RGB), 3 (mono), 9 (RLEmap), 10 (RLERGB), 11 (RLEmono) TGA images supported\n");
661 		return;
662 	}
663 
664 	/* validate color depth */
665 	switch (header.pixel_size) {
666 	case 8:
667 	case 15:
668 	case 16:
669 	case 24:
670 	case 32:
671 		break;
672 	default:
673 		ri.Sys_Error(ERR_DROP, "LoadTGA: Only 8, 15, 16, 24 and 32 bit images (with colormaps) supported\n");
674 		return;
675 	}
676 
677 	r = g = b = a = l = 0;
678 
679 	/* if required, read the color map information */
680 	ColorMap = NULL;
681 	mapped = (header.image_type == TGA_Map || header.image_type == TGA_RLEMap || header.image_type == TGA_CompMap || header.image_type == TGA_CompMap4) && header.colormap_type == 1;
682 	if (mapped) {
683 		/* validate colormap size */
684 		switch (header.colormap_size) {
685 		case 8:
686 		case 16:
687 		case 32:
688 		case 24:
689 			break;
690 		default:
691 			ri.Sys_Error(ERR_DROP, "LoadTGA: Only 8, 16, 24 and 32 bit colormaps supported\n");
692 			return;
693 		}
694 
695 		temp1 = header.colormap_index;
696 		temp2 = header.colormap_length;
697 		if ((temp1 + temp2 + 1) >= MAXCOLORS) {
698 			ri.FS_FreeFile(data);
699 			return;
700 		}
701 		ColorMap = (byte *) malloc(MAXCOLORS * 4);
702 		map_idx = 0;
703 		for (i = temp1; i < temp1 + temp2; ++i, map_idx += 4) {
704 
705 			/* read appropriate number of bytes, break into rgb & put in map */
706 			switch (header.colormap_size) {
707 			case 8:
708 				r = g = b = *pdata++;
709 				a = 255;
710 				break;
711 			case 15:
712 				j = *pdata++;
713 				k = *pdata++;
714 				l = ((unsigned int)k << 8) + j;
715 				r = (byte) (((k & 0x7C) >> 2) << 3);
716 				g = (byte) ((((k & 0x03) << 3) + ((j & 0xE0) >> 5)) << 3);
717 				b = (byte) ((j & 0x1F) << 3);
718 				a = 255;
719 				break;
720 			case 16:
721 				j = *pdata++;
722 				k = *pdata++;
723 				l = ((unsigned int)k << 8) + j;
724 				r = (byte) (((k & 0x7C) >> 2) << 3);
725 				g = (byte) ((((k & 0x03) << 3) + ((j & 0xE0) >> 5)) << 3);
726 				b = (byte) ((j & 0x1F) << 3);
727 				a = (k & 0x80) ? 255 : 0;
728 				break;
729 			case 24:
730 				b = *pdata++;
731 				g = *pdata++;
732 				r = *pdata++;
733 				a = 255;
734 				l = 0;
735 				break;
736 			case 32:
737 				b = *pdata++;
738 				g = *pdata++;
739 				r = *pdata++;
740 				a = *pdata++;
741 				l = 0;
742 				break;
743 			}
744 			ColorMap[map_idx + 0] = r;
745 			ColorMap[map_idx + 1] = g;
746 			ColorMap[map_idx + 2] = b;
747 			ColorMap[map_idx + 3] = a;
748 		}
749 	}
750 	/* check run-length encoding */
751 	rlencoded = header.image_type == TGA_RLEMap || header.image_type == TGA_RLERGB || header.image_type == TGA_RLEMono;
752 	RLE_count = 0;
753 	RLE_flag = 0;
754 
755 	w = header.width;
756 	h = header.height;
757 
758 	if (width)
759 		*width = w;
760 	if (height)
761 		*height = h;
762 
763 	size = w * h * 4;
764 	*pic = (byte *) malloc(size);
765 
766 	memset(*pic, 0, size);
767 
768 	/* read the Targa file body and convert to portable format */
769 	pixel_size = header.pixel_size;
770 	origin = (header.attributes & 0x20) >> 5;
771 	interleave = (header.attributes & 0xC0) >> 6;
772 	truerow = 0;
773 	baserow = 0;
774 	for (y = 0; y < h; y++) {
775 		realrow = truerow;
776 		if (origin == TGA_O_UPPER)
777 			realrow = h - realrow - 1;
778 
779 		dst = *pic + realrow * w * 4;
780 
781 		for (x = 0; x < w; x++) {
782 			/* check if run length encoded */
783 			if (rlencoded) {
784 				if (!RLE_count) {
785 					/* have to restart run */
786 					i = *pdata++;
787 					RLE_flag = (i & 0x80);
788 					if (!RLE_flag) {
789 						/* stream of unencoded pixels */
790 						RLE_count = i + 1;
791 					} else {
792 						/* single pixel replicated */
793 						RLE_count = i - 127;
794 					}
795 					/* decrement count & get pixel */
796 					--RLE_count;
797 				} else {
798 
799 					/* have already read count & (at least) first pixel */
800 					--RLE_count;
801 					if (RLE_flag)
802 						/* replicated pixels */
803 						goto PixEncode;
804 				}
805 			}
806 			/* read appropriate number of bytes, break into RGB */
807 			switch (pixel_size) {
808 			case 8:
809 				r = g = b = l = *pdata++;
810 				a = 255;
811 				break;
812 			case 15:
813 				j = *pdata++;
814 				k = *pdata++;
815 				l = ((unsigned int)k << 8) + j;
816 				r = (byte) (((k & 0x7C) >> 2) << 3);
817 				g = (byte) ((((k & 0x03) << 3) + ((j & 0xE0) >> 5)) << 3);
818 				b = (byte) ((j & 0x1F) << 3);
819 				a = 255;
820 				break;
821 			case 16:
822 				j = *pdata++;
823 				k = *pdata++;
824 				l = ((unsigned int)k << 8) + j;
825 				r = (byte) (((k & 0x7C) >> 2) << 3);
826 				g = (byte) ((((k & 0x03) << 3) + ((j & 0xE0) >> 5)) << 3);
827 				b = (byte) ((j & 0x1F) << 3);
828 				a = 255;
829 				break;
830 			case 24:
831 				b = *pdata++;
832 				g = *pdata++;
833 				r = *pdata++;
834 				a = 255;
835 				l = 0;
836 				break;
837 			case 32:
838 				b = *pdata++;
839 				g = *pdata++;
840 				r = *pdata++;
841 				a = *pdata++;
842 				l = 0;
843 				break;
844 			default:
845 				ri.Sys_Error(ERR_DROP, "Illegal pixel_size '%d' in file '%s'\n", filename);
846 				return;
847 			}
848 
849 	PixEncode:
850 			if (mapped) {
851 				map_idx = l * 4;
852 				*dst++ = ColorMap[map_idx + 0];
853 				*dst++ = ColorMap[map_idx + 1];
854 				*dst++ = ColorMap[map_idx + 2];
855 				*dst++ = ColorMap[map_idx + 3];
856 			} else {
857 				*dst++ = r;
858 				*dst++ = g;
859 				*dst++ = b;
860 				*dst++ = a;
861 			}
862 		}
863 
864 		if (interleave == TGA_IL_Four)
865 			truerow += 4;
866 		else if (interleave == TGA_IL_Two)
867 			truerow += 2;
868 		else
869 			truerow++;
870 
871 		if (truerow >= h)
872 			truerow = ++baserow;
873 	}
874 
875 	if (mapped)
876 		free(ColorMap);
877 
878 	ri.FS_FreeFile(data);
879 }
880 
881 /*
882  * =================================================================
883  *
884  * JPEG LOADING
885  *
886  * By Robert 'Heffo' Heffernan
887  *
888  * =================================================================
889  */
890 
891 void
jpg_null(j_decompress_ptr cinfo)892 jpg_null(j_decompress_ptr cinfo)
893 {
894 }
895 
896 boolean
jpg_fill_input_buffer(j_decompress_ptr cinfo)897 jpg_fill_input_buffer(j_decompress_ptr cinfo)
898 {
899 	ri.Con_Printf(PRINT_ALL, "Premature end of JPEG data\n");
900 	return 1;
901 }
902 
903 void
jpg_skip_input_data(j_decompress_ptr cinfo,long num_bytes)904 jpg_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
905 {
906 
907 	cinfo->src->next_input_byte += (size_t) num_bytes;
908 	cinfo->src->bytes_in_buffer -= (size_t) num_bytes;
909 
910 	if (cinfo->src->bytes_in_buffer < 0)
911 		ri.Con_Printf(PRINT_ALL, "Premature end of JPEG data\n");
912 }
913 
914 void
local_jpeg_mem_src(j_decompress_ptr cinfo,byte * mem,int len)915 local_jpeg_mem_src(j_decompress_ptr cinfo, byte * mem, int len)
916 {
917 	cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(struct jpeg_source_mgr));
918 	cinfo->src->init_source = jpg_null;
919 	cinfo->src->fill_input_buffer = jpg_fill_input_buffer;
920 	cinfo->src->skip_input_data = jpg_skip_input_data;
921 	cinfo->src->resync_to_restart = jpeg_resync_to_restart;
922 	cinfo->src->term_source = jpg_null;
923 	cinfo->src->bytes_in_buffer = len;
924 	cinfo->src->next_input_byte = mem;
925 }
926 
927 /*
928  * ============== LoadJPG ==============
929  */
930 void
LoadJPG(char * filename,byte ** pic,int * width,int * height)931 LoadJPG(char *filename, byte ** pic, int *width, int *height)
932 {
933 	struct jpeg_decompress_struct cinfo;
934 	struct jpeg_error_mgr jerr;
935 	byte           *rawdata, *rgbadata, *scanline, *p, *q;
936 	int		rawsize, i;
937 
938 	*pic = NULL;
939 
940 	/* Load JPEG file into memory */
941 	rawsize = ri.FS_LoadFile(filename, (void **)&rawdata);
942 	if (!rawdata)
943 		return;
944 
945 	/* Knightmare- check for bad data  */
946 	if (rawdata[6] != 'J'
947 	    || rawdata[7] != 'F'
948 	    || rawdata[8] != 'I'
949 	    || rawdata[9] != 'F') {
950 		ri.Con_Printf(PRINT_ALL, "Bad jpg file %s\n", filename);
951 		ri.FS_FreeFile(rawdata);
952 		return;
953 	}
954 	/* Initialise libJpeg Object */
955 	cinfo.err = jpeg_std_error(&jerr);
956 	jpeg_create_decompress(&cinfo);
957 
958 	/* Feed JPEG memory into the libJpeg Object */
959 	local_jpeg_mem_src(&cinfo, rawdata, rawsize);
960 
961 	/* Process JPEG header */
962 	jpeg_read_header(&cinfo, true);
963 
964 	/* Start Decompression */
965 	jpeg_start_decompress(&cinfo);
966 
967 	/* Check Colour Components */
968 	if (cinfo.output_components != 3) {
969 		ri.Con_Printf(PRINT_ALL, "Invalid JPEG colour components\n");
970 		jpeg_destroy_decompress(&cinfo);
971 		ri.FS_FreeFile(rawdata);
972 		return;
973 	}
974 	/* Allocate Memory for decompressed image */
975 	rgbadata = malloc(cinfo.output_width * cinfo.output_height * 4);
976 	if (!rgbadata) {
977 		ri.Con_Printf(PRINT_ALL, "Insufficient RAM for JPEG buffer\n");
978 		jpeg_destroy_decompress(&cinfo);
979 		ri.FS_FreeFile(rawdata);
980 		return;
981 	}
982 	/* Pass sizes to output */
983 	*width = cinfo.output_width;
984 	*height = cinfo.output_height;
985 
986 	/* Allocate Scanline buffer */
987 	scanline = malloc(cinfo.output_width * 3);
988 	if (!scanline) {
989 		ri.Con_Printf(PRINT_ALL, "Insufficient RAM for JPEG scanline buffer\n");
990 		free(rgbadata);
991 		jpeg_destroy_decompress(&cinfo);
992 		ri.FS_FreeFile(rawdata);
993 		return;
994 	}
995 	/* Read Scanlines, and expand from RGB to RGBA */
996 	q = rgbadata;
997 	while (cinfo.output_scanline < cinfo.output_height) {
998 		p = scanline;
999 		jpeg_read_scanlines(&cinfo, &scanline, 1);
1000 
1001 		for (i = 0; i < cinfo.output_width; i++) {
1002 			q[0] = p[0];
1003 			q[1] = p[1];
1004 			q[2] = p[2];
1005 			q[3] = 255;
1006 
1007 			p += 3;
1008 			q += 4;
1009 		}
1010 	}
1011 
1012 	/* Free the scanline buffer */
1013 	free(scanline);
1014 
1015 	/* Finish Decompression */
1016 	jpeg_finish_decompress(&cinfo);
1017 
1018 	/* Destroy JPEG object */
1019 	jpeg_destroy_decompress(&cinfo);
1020 
1021 	/* Return the 'rgbadata' */
1022 	*pic = rgbadata;
1023 }
1024 
1025 
1026 /*
1027  * =============================================================
1028  *
1029  * PNG STUFF
1030  *
1031  * =============================================================
1032  */
1033 
1034 typedef struct png_s {			/* TPng = class(TGraphic) */
1035 	char           *tmpBuf;
1036 	int		tmpi;
1037 	long		FBgColor;	/* DL Background color Added 30/05/2000 */
1038 	int		FTransparent;	/* DL Is this Image Transparent Added 30/05/2000 */
1039 	long		FRowBytes;	/* DL Added 30/05/2000 */
1040 	double		FGamma;		/* DL Added 07/06/2000 */
1041 	double		FScreenGamma;	/* DL Added 07/06/2000 */
1042 	char           *FRowPtrs;	/* DL Changed for consistancy 30/05/2000   */
1043 	char           *Data;		/* property Data: pByte read fData; */
1044 	char           *Title;
1045 	char           *Author;
1046 	char           *Description;
1047 	int		BitDepth;
1048 	int		BytesPerPixel;
1049 	int		ColorType;
1050 	unsigned long	Height;
1051 	unsigned long	Width;
1052 	int		Interlace;
1053 	int		Compression;
1054 	int		Filter;
1055 	double		LastModified;
1056 	int		Transparent;
1057 } png_t;
1058 
1059 png_t          *my_png = 0;
1060 unsigned char  *pngbytes;
1061 
1062 void
InitializeDemData()1063 InitializeDemData()
1064 {
1065 	long           *cvaluep;/* ub */
1066 	long		y;
1067 
1068 	/* Initialize Data and RowPtrs */
1069 	if (my_png->Data) {
1070 		free(my_png->Data);
1071 		my_png->Data = 0;
1072 	}
1073 	if (my_png->FRowPtrs) {
1074 		free(my_png->FRowPtrs);
1075 		my_png->FRowPtrs = 0;
1076 	}
1077 	my_png->Data = malloc(my_png->Height * my_png->FRowBytes);	/* DL Added 30/5/2000 */
1078 	my_png->FRowPtrs = malloc(sizeof(void *) * my_png->Height);
1079 
1080 	if ((my_png->Data) && (my_png->FRowPtrs)) {
1081 		cvaluep = (long *)my_png->FRowPtrs;
1082 		for (y = 0; y < my_png->Height; y++) {
1083 			cvaluep[y] = (long)my_png->Data + (y * (long)my_png->FRowBytes); /* DL Added 08/07/2000 */
1084 		}
1085 	}
1086 }
1087 
1088 void
mypng_struct_create()1089 mypng_struct_create()
1090 {
1091 	if (my_png)
1092 		return;
1093 	my_png = malloc(sizeof(png_t));
1094 	my_png->Data = 0;
1095 	my_png->FRowPtrs = 0;
1096 	my_png->Height = 0;
1097 	my_png->Width = 0;
1098 	my_png->ColorType = PNG_COLOR_TYPE_RGB;
1099 	my_png->Interlace = PNG_INTERLACE_NONE;
1100 	my_png->Compression = PNG_COMPRESSION_TYPE_DEFAULT;
1101 	my_png->Filter = PNG_FILTER_TYPE_DEFAULT;
1102 }
1103 
1104 void
mypng_struct_destroy(qboolean keepData)1105 mypng_struct_destroy(qboolean keepData)
1106 {
1107 	if (!my_png)
1108 		return;
1109 	if (my_png->Data && !keepData)
1110 		free(my_png->Data);
1111 	if (my_png->FRowPtrs)
1112 		free(my_png->FRowPtrs);
1113 	free(my_png);
1114 	my_png = 0;
1115 }
1116 
1117 /*
1118  * =============================================================
1119  *
1120  * fReadData
1121  *
1122  * =============================================================
1123  */
1124 
1125 void PNGAPI
fReadData(png_structp png,png_bytep data,png_size_t length)1126 fReadData(png_structp png, png_bytep data, png_size_t length)
1127 {				/* called by pnglib */
1128 	int		i;
1129 
1130 	for (i = 0; i < length; i++)
1131 		data[i] = my_png->tmpBuf[my_png->tmpi++];	/* give pnglib a some more bytes   */
1132 }
1133 
1134 /*
1135  * =============================================================
1136  *
1137  * LoadPNG
1138  *
1139  * =============================================================
1140  */
1141 
1142 void
LoadPNG(char * filename,byte ** pic,int * width,int * height)1143 LoadPNG(char *filename, byte ** pic, int *width, int *height)
1144 {
1145 	png_structp	png;
1146 	png_infop	pnginfo;
1147 	byte		ioBuffer  [8192];
1148 	int		len;
1149 	byte           *raw;
1150 
1151 	*pic = 0;
1152 
1153 	len = ri.FS_LoadFile(filename, (void **)&raw);
1154 
1155 	if (!raw) {
1156 		ri.Con_Printf(PRINT_DEVELOPER, "Bad png file %s\n", filename);
1157 		return;
1158 	}
1159 	if (png_sig_cmp(raw, 0, 4))
1160 		return;
1161 
1162 	png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
1163 	if (!png)
1164 		return;
1165 
1166 	pnginfo = png_create_info_struct(png);
1167 
1168 	if (!pnginfo) {
1169 		png_destroy_read_struct(&png, &pnginfo, 0);
1170 		return;
1171 	}
1172 	png_set_sig_bytes(png, 0 /* sizeof( sig ) */ );
1173 
1174 	mypng_struct_create();	/* creates the my_png struct */
1175 
1176 	my_png->tmpBuf = (char *)raw;	/* buf = whole file content */
1177 	my_png->tmpi = 0;
1178 
1179 	png_set_read_fn(png, ioBuffer, fReadData);
1180 
1181 	png_read_info(png, pnginfo);
1182 
1183 	png_get_IHDR(png, pnginfo, &my_png->Width, &my_png->Height, &my_png->BitDepth, &my_png->ColorType, &my_png->Interlace, &my_png->Compression, &my_png->Filter);
1184 
1185 	/* ...removed bgColor code here... */
1186 	if (my_png->ColorType == PNG_COLOR_TYPE_PALETTE)
1187 		png_set_palette_to_rgb(png);
1188 	if (my_png->ColorType == PNG_COLOR_TYPE_GRAY && my_png->BitDepth < 8)
1189 		png_set_gray_1_2_4_to_8(png);
1190 
1191 	/* Add alpha channel if present */
1192 	if (png_get_valid(png, pnginfo, PNG_INFO_tRNS))
1193 		png_set_tRNS_to_alpha(png);
1194 
1195 	/* hax: expand 24bit to 32bit */
1196 	if (my_png->BitDepth == 8 && my_png->ColorType == PNG_COLOR_TYPE_RGB)
1197 		png_set_filler(png, 255, PNG_FILLER_AFTER);
1198 
1199 	if ((my_png->ColorType == PNG_COLOR_TYPE_GRAY) || (my_png->ColorType == PNG_COLOR_TYPE_GRAY_ALPHA))
1200 		png_set_gray_to_rgb(png);
1201 
1202 
1203 	if (my_png->BitDepth < 8)
1204 		png_set_expand(png);
1205 
1206 	/* update the info structure */
1207 	png_read_update_info(png, pnginfo);
1208 
1209 	my_png->FRowBytes = png_get_rowbytes(png, pnginfo);
1210 	my_png->BytesPerPixel = png_get_channels(png, pnginfo);	/* DL Added 30/08/2000 */
1211 
1212 	InitializeDemData();
1213 	if ((my_png->Data) && (my_png->FRowPtrs))
1214 		png_read_image(png, (png_bytepp) my_png->FRowPtrs);
1215 
1216 	png_read_end(png, pnginfo);	/* read last information chunks */
1217 
1218 	png_destroy_read_struct(&png, &pnginfo, 0);
1219 
1220 
1221 	/* only load 32 bit by now... */
1222 	if (my_png->BitDepth == 8) {
1223 		*pic = (byte *)my_png->Data;
1224 		*width = my_png->Width;
1225 		*height = my_png->Height;
1226 	} else {
1227 		ri.Con_Printf(PRINT_DEVELOPER, "Bad png color depth: %s\n", filename);
1228 		*pic = NULL;
1229 		free(my_png->Data);
1230 	}
1231 
1232 	mypng_struct_destroy(true);
1233 	ri.FS_FreeFile((void *)raw);
1234 }
1235 
1236 /*
1237  * ====================================================================
1238  *
1239  * IMAGE FLOOD FILLING
1240  *
1241  * ====================================================================
1242  */
1243 
1244 
1245 /*
1246  * ================= Mod_FloodFillSkin
1247  *
1248  * Fill background pixels so mipmapping doesn't have haloes =================
1249  */
1250 
1251 typedef struct {
1252 	short		x, y;
1253 } floodfill_t;
1254 
1255 /* must be a power of 2 */
1256 #define FLOODFILL_FIFO_SIZE 0x1000
1257 #define FLOODFILL_FIFO_MASK (FLOODFILL_FIFO_SIZE - 1)
1258 
1259 #define FLOODFILL_STEP( off, dx, dy ) \
1260 { \
1261 	if (pos[off] == fillcolor) \
1262 	{ \
1263 		pos[off] = 255; \
1264 		fifo[inpt].x = x + (dx), fifo[inpt].y = y + (dy); \
1265 		inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; \
1266 	} \
1267 	else if (pos[off] != 255) fdc = pos[off]; \
1268 }
1269 
1270 void
R_FloodFillSkin(byte * skin,int skinwidth,int skinheight)1271 R_FloodFillSkin(byte * skin, int skinwidth, int skinheight)
1272 {
1273 	byte		fillcolor = *skin;	/* assume this is the pixel to fill */
1274 	floodfill_t	fifo[FLOODFILL_FIFO_SIZE];
1275 	int		inpt = 0, outpt = 0;
1276 	int		filledcolor = -1;
1277 	int		i;
1278 
1279 	if (filledcolor == -1) {
1280 		filledcolor = 0;
1281 		/* attempt to find opaque black */
1282 		for (i = 0; i < 256; ++i)
1283 			if (d_8to24table[i] == (255 << 0)) {	/* alpha 1.0 */
1284 				filledcolor = i;
1285 				break;
1286 			}
1287 	}
1288 
1289 	/* can't fill to filled color or to transparent color (used as visited marker) */
1290 	if ((fillcolor == filledcolor) || (fillcolor == 255)) {
1291 
1292 		/* printf( "not filling skin from %d to %d\n", fillcolor, filledcolor ); */
1293 		return;
1294 	}
1295 	fifo[inpt].x = 0, fifo[inpt].y = 0;
1296 	inpt = (inpt + 1) & FLOODFILL_FIFO_MASK;
1297 
1298 	while (outpt != inpt) {
1299 		int		x = fifo[outpt].x, y = fifo[outpt].y;
1300 		int		fdc = filledcolor;
1301 		byte           *pos = &skin[x + skinwidth * y];
1302 
1303 		outpt = (outpt + 1) & FLOODFILL_FIFO_MASK;
1304 
1305 		if (x > 0)
1306 			FLOODFILL_STEP(-1, -1, 0);
1307 		if (x < skinwidth - 1)
1308 			FLOODFILL_STEP(1, 1, 0);
1309 		if (y > 0)
1310 			FLOODFILL_STEP(-skinwidth, 0, -1);
1311 		if (y < skinheight - 1)
1312 			FLOODFILL_STEP(skinwidth, 0, 1);
1313 		skin[x + skinwidth * y] = fdc;
1314 	}
1315 }
1316 
1317 /* ======================================================= */
1318 
1319 
1320 /*
1321  * ================ GL_ResampleTexture ================
1322  */
1323 void
GL_ResampleTexture(unsigned * in,int inwidth,int inheight,unsigned * out,int outwidth,int outheight)1324 GL_ResampleTexture(unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight)
1325 {
1326 	int		i, j;
1327 	unsigned       *inrow, *inrow2;
1328 	unsigned	frac, fracstep;
1329 	unsigned	p1[1024], p2[1024];
1330 	byte           *pix1, *pix2, *pix3, *pix4;
1331 
1332 	fracstep = inwidth * 0x10000 / outwidth;
1333 
1334 	frac = fracstep >> 2;
1335 	for (i = 0; i < outwidth; i++) {
1336 		p1[i] = 4 * (frac >> 16);
1337 		frac += fracstep;
1338 	}
1339 	frac = 3 * (fracstep >> 2);
1340 	for (i = 0; i < outwidth; i++) {
1341 		p2[i] = 4 * (frac >> 16);
1342 		frac += fracstep;
1343 	}
1344 
1345 	for (i = 0; i < outheight; i++, out += outwidth) {
1346 		inrow = in + inwidth * (int)((i + 0.25) * inheight / outheight);
1347 		inrow2 = in + inwidth * (int)((i + 0.75) * inheight / outheight);
1348 		frac = fracstep >> 1;
1349 		for (j = 0; j < outwidth; j++) {
1350 			pix1 = (byte *) inrow + p1[j];
1351 			pix2 = (byte *) inrow + p2[j];
1352 			pix3 = (byte *) inrow2 + p1[j];
1353 			pix4 = (byte *) inrow2 + p2[j];
1354 			((byte *) (out + j))[0] = (pix1[0] + pix2[0] + pix3[0] + pix4[0]) >> 2;
1355 			((byte *) (out + j))[1] = (pix1[1] + pix2[1] + pix3[1] + pix4[1]) >> 2;
1356 			((byte *) (out + j))[2] = (pix1[2] + pix2[2] + pix3[2] + pix4[2]) >> 2;
1357 			((byte *) (out + j))[3] = (pix1[3] + pix2[3] + pix3[3] + pix4[3]) >> 2;
1358 		}
1359 	}
1360 }
1361 
1362 /*
1363  * ================ GL_LightScaleTexture
1364  *
1365  * Scale up the pixel values in a texture to increase the lighting range
1366  * ================
1367  */
1368 void
GL_LightScaleTexture(unsigned * in,int inwidth,int inheight,qboolean only_gamma)1369 GL_LightScaleTexture(unsigned *in, int inwidth, int inheight, qboolean only_gamma)
1370 {
1371 	if (only_gamma) {
1372 		double		i, c;
1373 		byte           *p;
1374 
1375 		p = (byte *) in;
1376 
1377 		c = inwidth * inheight;
1378 		for (i = 0; i < c; i++, p += 4) {
1379 			p[0] = gammatable[p[0]];
1380 			p[1] = gammatable[p[1]];
1381 			p[2] = gammatable[p[2]];
1382 		}
1383 	} else {
1384 		double		i, c;
1385 		byte           *p;
1386 
1387 		p = (byte *) in;
1388 
1389 		c = inwidth * inheight;
1390 		for (i = 0; i < c; i++, p += 4) {
1391 			p[0] = gammatable[intensitytable[p[0]]];
1392 			p[1] = gammatable[intensitytable[p[1]]];
1393 			p[2] = gammatable[intensitytable[p[2]]];
1394 		}
1395 	}
1396 }
1397 
1398 /*
1399  * ================ GL_MipMap
1400  *
1401  * Operates in place, quartering the size of the texture ================
1402  */
1403 void
GL_MipMap(byte * in,int width,int height)1404 GL_MipMap(byte * in, int width, int height)
1405 {
1406 	int		i, j;
1407 	byte           *out;
1408 
1409 	width <<= 2;
1410 	height >>= 1;
1411 	out = in;
1412 	for (i = 0; i < height; i++, in += width) {
1413 		for (j = 0; j < width; j += 8, out += 4, in += 8) {
1414 			out[0] = (in[0] + in[4] + in[width + 0] + in[width + 4]) >> 2;
1415 			out[1] = (in[1] + in[5] + in[width + 1] + in[width + 5]) >> 2;
1416 			out[2] = (in[2] + in[6] + in[width + 2] + in[width + 6]) >> 2;
1417 			out[3] = (in[3] + in[7] + in[width + 3] + in[width + 7]) >> 2;
1418 		}
1419 	}
1420 }
1421 
1422 /*
1423  * =============== GL_Upload32
1424  *
1425  * Returns has_alpha ===============
1426  */
1427 void
GL_BuildPalettedTexture(unsigned char * paletted_texture,unsigned char * scaled,int scaled_width,int scaled_height)1428 GL_BuildPalettedTexture(unsigned char *paletted_texture, unsigned char *scaled, int scaled_width, int scaled_height)
1429 {
1430 	double		i;
1431 
1432 	for (i = 0; i < (double)(scaled_width) * (double)(scaled_height); i++) {
1433 		unsigned int	r , g, b, c;
1434 
1435 		r = (scaled[0] >> 3) & 31;
1436 		g = (scaled[1] >> 2) & 63;
1437 		b = (scaled[2] >> 3) & 31;
1438 
1439 		c = r | (g << 5) | (b << 11);
1440 
1441 		paletted_texture[(int)(i)] = gl_state.d_16to8table[c];
1442 
1443 		scaled += 4;
1444 	}
1445 }
1446 
1447 /*
1448  * =============== here starts modified code by Heffo/changes by Nexus
1449  * ===============
1450  */
1451 
1452 
1453 int		upload_width, upload_height;
1454 qboolean	uploaded_paletted;
1455 
1456 int
nearest_power_of_2(int size)1457 nearest_power_of_2(int size)
1458 {
1459 	int		i = 2;
1460 
1461 	/* NeVo - infinite loop bug-fix */
1462 	if (size == 1)
1463 		return size;
1464 
1465 	while (1) {
1466 		i <<= 1;
1467 		if (size == i)
1468 			return i;
1469 		if (size > i && size < (i << 1)) {
1470 			if (size >= ((i + (i << 1)) / 2))
1471 				return i << 1;
1472 			else
1473 				return i;
1474 		}
1475 	};
1476 }
1477 
1478 extern cvar_t  *gl_lightmap_texture_saturation;	/* jitsaturation */
1479 void
desaturate_texture(unsigned * udata,int width,int height)1480 desaturate_texture(unsigned *udata, int width, int height)
1481 {				/* jitsaturation */
1482 	int		i, size;
1483 	float		r, g, b, v, s;
1484 	unsigned char  *data;
1485 
1486 	data = (unsigned char *)udata;
1487 
1488 	s = gl_lightmap_texture_saturation->value;
1489 
1490 	size = width * height * 4;
1491 
1492 	for (i = 0; i < size; i += 4) {
1493 		r = data[i];
1494 		g = data[i + 1];
1495 		b = data[i + 2];
1496 		v = r * 0.30 + g * 0.59 + b * 0.11;
1497 
1498 		data[i] = (1 - s) * v + s * r;
1499 		data[i + 1] = (1 - s) * v + s * g;
1500 		data[i + 2] = (1 - s) * v + s * b;
1501 	}
1502 }
1503 
1504 /*
1505  * =============== GL_Upload32
1506  *
1507  * Returns has_alpha ===============
1508  */
1509 qboolean
GL_Upload32(unsigned * data,int width,int height,qboolean mipmap)1510 GL_Upload32(unsigned *data, int width, int height, qboolean mipmap)
1511 {
1512 	int		samples;
1513 	unsigned       *scaled;
1514 	int		scaled_width = 0, scaled_height = 0;
1515 	int		i, c;
1516 	byte           *scan;
1517 	int		comp = 0;
1518 
1519 	uploaded_paletted = false;
1520 
1521 	/* don't ever bother with maxtexsize textures */
1522 	if (qglColorTableEXT && gl_ext_palettedtexture->value) {	/* palettedtexture is limited to 256 */
1523 		clamp(scaled_width, 1, 256);
1524 		clamp(scaled_height, 1, 256);
1525 	} else {
1526 		clamp(scaled_width, 1, gl_state.maxtexsize);
1527 		clamp(scaled_height, 1, gl_state.maxtexsize);
1528 	}
1529 
1530 	/* scan the texture for any non-255 alpha */
1531 	c = width * height;
1532 	scan = ((byte *) data) + 3;
1533 	samples = gl_solid_format;
1534 	for (i = 0; i < c; i++, scan += 4) {
1535 		if (*scan != 255) {
1536 			samples = gl_alpha_format;
1537 			break;
1538 		}
1539 	}
1540 
1541 	/* Heffo - ARB Texture Compression */
1542 	qglHint(GL_TEXTURE_COMPRESSION_HINT_ARB, GL_NICEST);
1543 	if (samples == gl_solid_format)
1544 		comp = (gl_state.texture_compression) ? GL_COMPRESSED_RGB_ARB : gl_tex_solid_format;
1545 	else if (samples == gl_alpha_format)
1546 		comp = (gl_state.texture_compression) ? GL_COMPRESSED_RGBA_ARB : gl_tex_alpha_format;
1547 
1548 
1549 	/* find sizes to scale to */
1550 	{
1551 		int		max_size;
1552 
1553 		qglGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_size);
1554 		scaled_width = nearest_power_of_2(width);
1555 		scaled_height = nearest_power_of_2(height);
1556 
1557 		if (scaled_width > max_size)
1558 			scaled_width = max_size;
1559 		if (scaled_height > max_size)
1560 			scaled_height = max_size;
1561 
1562 		if (scaled_width < 2)
1563 			scaled_width = 2;
1564 		if (scaled_height < 2)
1565 			scaled_height = 2;
1566 	}
1567 
1568 	/* let people sample down the world textures for speed */
1569 	if (mipmap && (int)gl_picmip->value > 0) {
1570 		int		maxsize;
1571 
1572 		if ((int)gl_picmip->value == 1)		/* clamp to 512x512 */
1573 			maxsize = 512;
1574 		else if ((int)gl_picmip->value == 2)	/* clamp to 256x256 */
1575 			maxsize = 256;
1576 		else					/* clamp to 128x128 */
1577 			maxsize = 128;
1578 
1579 		while (1) {
1580 			if (scaled_width <= maxsize && scaled_height <= maxsize)
1581 				break;
1582 			scaled_width >>= 1;
1583 			scaled_height >>= 1;
1584 		}
1585 	}
1586 	if (scaled_width != width || scaled_height != height) {
1587 		scaled = malloc((scaled_width * scaled_height) * 4);
1588 		GL_ResampleTexture(data, width, height, scaled, scaled_width, scaled_height);
1589 	} else {
1590 		scaled_width = width;
1591 		scaled_height = height;
1592 		scaled = data;
1593 	}
1594 
1595 	if (gl_lightmap_texture_saturation->value < 1)	/* jitsaturation */
1596 		desaturate_texture(scaled, scaled_width, scaled_height);
1597 
1598 	if (mipmap) {
1599 		if (!gl_state.hwgamma)
1600 			if (brightenTexture)
1601 				GL_LightScaleTexture(scaled, scaled_width, scaled_height, !mipmap);
1602 
1603 		if (gl_state.sgis_mipmap) {
1604 			qglTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, true);
1605 			qglTexImage2D(GL_TEXTURE_2D, 0, comp, scaled_width, scaled_height, 0,
1606 			              GL_RGBA, GL_UNSIGNED_BYTE, scaled);
1607 		} else
1608 			gluBuild2DMipmaps(GL_TEXTURE_2D, samples, scaled_width, scaled_height,
1609 			                  GL_RGBA, GL_UNSIGNED_BYTE, scaled);
1610 	} else {
1611 		if (!gl_state.hwgamma)
1612 			if (brightenTexture)
1613 				GL_LightScaleTexture(scaled, scaled_width, scaled_height, !mipmap);
1614 		qglTexImage2D(GL_TEXTURE_2D, 0, comp, scaled_width, scaled_height, 0,
1615 		              GL_RGBA, GL_UNSIGNED_BYTE, scaled);
1616 	}
1617 
1618 	if (scaled_width != width || scaled_height != height)
1619 		free(scaled);
1620 
1621 
1622 	upload_width = scaled_width;
1623 	upload_height = scaled_height;
1624 
1625 	qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (mipmap) ? gl_filter_min : gl_filter_max);
1626 	qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
1627 
1628 
1629 	if (mipmap) {
1630 
1631 		/* Set anisotropic filter if supported and enabled Knightmare */
1632 		if (gl_config.anisotropic && gl_anisotropic->value)
1633 			qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_anisotropic->value);
1634 		else
1635 			qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
1636 
1637 	}
1638 	return (samples == gl_alpha_format);
1639 }
1640 
1641 
1642 /*
1643  * =============== GL_Upload8
1644  *
1645  * Returns has_alpha ===============
1646  */
1647 
1648 qboolean
GL_Upload8(byte * data,int width,int height,qboolean mipmap,qboolean is_sky)1649 GL_Upload8(byte * data, int width, int height, qboolean mipmap, qboolean is_sky)
1650 {
1651 	unsigned	trans[512 * 256];
1652 	int		i, s;
1653 	int		p;
1654 
1655 	s = width * height;
1656 
1657 	if (s > sizeof(trans) / 4)
1658 		ri.Sys_Error(ERR_DROP, "GL_Upload8: too large");
1659 
1660 	/*
1661 	if ( is_sky ) {
1662 	  	qglTexImage2D( GL_TEXTURE_2D, 0,
1663 	                       GL_COLOR_INDEX8_EXT, width, height, 0, GL_COLOR_INDEX,
1664 	                       GL_UNSIGNED_BYTE, data );
1665 	  	qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
1666 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
1667 	} else
1668 	*/
1669 	{
1670 		for (i = 0; i < s; i++) {
1671 			p = data[i];
1672 			trans[i] = d_8to24table[p];
1673 
1674 			if (p == 255) {	/* transparent, so scan around for another color */
1675 				/* to avoid alpha fringes */
1676 				/*
1677 				 * FIXME: do a full flood fill so mips
1678 				 * work...
1679 				 */
1680 				if (i > width && data[i - width] != 255)
1681 					p = data[i - width];
1682 				else if (i < s - width && data[i + width] != 255)
1683 					p = data[i + width];
1684 				else if (i > 0 && data[i - 1] != 255)
1685 					p = data[i - 1];
1686 				else if (i < s - 1 && data[i + 1] != 255)
1687 					p = data[i + 1];
1688 				else
1689 					p = 0;
1690 				/* copy rgb components */
1691 				((byte *) & trans[i])[0] = ((byte *) & d_8to24table[p])[0];
1692 				((byte *) & trans[i])[1] = ((byte *) & d_8to24table[p])[1];
1693 				((byte *) & trans[i])[2] = ((byte *) & d_8to24table[p])[2];
1694 			}
1695 		}
1696 
1697 		return GL_Upload32(trans, width, height, mipmap);
1698 	}
1699 }
1700 
1701 /*
1702  * ================ GL_LoadPic
1703  *
1704  * This is also used as an entry point for the generated r_notexture
1705  * ================
1706  */
1707 image_t        *
GL_LoadPic(char * name,byte * pic,int width,int height,imagetype_t type,int bits)1708 GL_LoadPic(char *name, byte * pic, int width, int height, imagetype_t type, int bits)
1709 {
1710 	image_t        *image;
1711 	int		i;
1712 #ifdef RETEX
1713 	/* NiceAss: Nexus'added vars for texture scaling */
1714 	miptex_t       *mt;
1715 	int		len;
1716 	char		s[128];
1717 #endif
1718 
1719 	/* find a free image_t */
1720 	for (i = 0, image = gltextures; i < numgltextures; i++, image++) {
1721 		if (!image->texnum)
1722 			break;
1723 	}
1724 	if (i == numgltextures) {
1725 		if (numgltextures == MAX_GLTEXTURES)
1726 			ri.Sys_Error(ERR_DROP, "MAX_GLTEXTURES");
1727 		numgltextures++;
1728 	}
1729 	image = &gltextures[i];
1730 
1731 	if (strlen(name) >= sizeof(image->name))
1732 		ri.Sys_Error(ERR_DROP, "Draw_LoadPic: \"%s\" is too long", name);
1733 	Q_strncpyz(image->name, name, sizeof(image->name));
1734 	image->registration_sequence = registration_sequence;
1735 
1736 	image->width = width;
1737 	image->height = height;
1738 	image->type = type;
1739 
1740 	image->replace_scale = 1.0;
1741 
1742 #ifdef RETEX
1743 	/* NiceAss: Nexus's image replacement scaling code  */
1744 	len = strlen(name);
1745 	Q_strncpyz(s, name, sizeof(s));
1746 
1747 	if (!strcmp(s + len - 4, ".tga") || !strcmp(s + len - 4, ".png") || !strcmp(s + len - 4, ".jpg")) {
1748 		s[len - 3] = 'w';
1749 		s[len - 2] = 'a';
1750 		s[len - 1] = 'l';				/* replace extension  */
1751 		ri.FS_LoadFile(s, (void **)&mt);		/* load .wal file  */
1752 
1753 		if (mt) {
1754 			image->width = LittleLong(mt->width);	/* grab size from wal  */
1755 			image->height = LittleLong(mt->height);
1756 			ri.FS_FreeFile((void *)mt);		/* free the picture  */
1757 		} else {					/* if it's replacing a PCX image */
1758 			byte           *pic, *palette;
1759 			int		pcxwidth  , pcxheight;
1760 
1761 			s[len - 3] = 'p';
1762 			s[len - 2] = 'c';
1763 			s[len - 1] = 'x';					/* replace extension */
1764 			LoadPCX(s, &pic, &palette, &pcxwidth, &pcxheight);	/* load .pcx file */
1765 
1766 			if (pcxwidth > 0 && pcxheight > 0) {
1767 				image->replace_scale = ((float)pcxwidth / image->width + (float)pcxheight / image->height) * 0.5;
1768 				if (image->replace_scale == 0.0)
1769 					image->replace_scale = 1.0;
1770 				image->replace_scale = MIN(image->replace_scale, 1.0);
1771 			}
1772 			if (pic)
1773 				free(pic);
1774 			if (palette)
1775 				free(palette);
1776 		}
1777 	}
1778 #endif
1779 
1780 	if (type == it_skin && bits == 8)
1781 		R_FloodFillSkin(pic, width, height);
1782 
1783 	/* load little pics into the scrap */
1784 	if (image->type == it_pic && bits == 8 && image->width < 64 && image->height < 64) {
1785 		int		x         , y;
1786 		int		i         , j, k;
1787 		int		texnum;
1788 
1789 		texnum = Scrap_AllocBlock(image->width, image->height, &x, &y);
1790 		if (texnum == -1)
1791 			goto nonscrap;
1792 		scrap_dirty = true;
1793 
1794 		/* copy the texels into the scrap block */
1795 		k = 0;
1796 		for (i = 0; i < image->height; i++)
1797 			for (j = 0; j < image->width; j++, k++)
1798 				scrap_texels[texnum][(y + i) * BLOCK_WIDTH + x + j] = pic[k];
1799 		image->texnum = TEXNUM_SCRAPS + texnum;
1800 		image->scrap = true;
1801 		image->has_alpha = true;
1802 		image->sl = (x + 0.01) / (float)BLOCK_WIDTH;
1803 		image->sh = (x + image->width - 0.01) / (float)BLOCK_WIDTH;
1804 		image->tl = (y + 0.01) / (float)BLOCK_WIDTH;
1805 		image->th = (y + image->height - 0.01) / (float)BLOCK_WIDTH;
1806 	} else {
1807 nonscrap:
1808 		image->scrap = false;
1809 		image->texnum = TEXNUM_IMAGES + (image - gltextures);
1810 		GL_Bind(image->texnum);
1811 		if (bits == 8)
1812 			image->has_alpha =
1813 			    GL_Upload8(pic, width, height, (image->type != it_pic && image->type != it_sky),
1814 			    image->type == it_sky);
1815 		else
1816 			image->has_alpha =
1817 			    GL_Upload32((unsigned *)pic, width, height,
1818 			    (image->type != it_pic && image->type != it_sky));
1819 		image->upload_width = upload_width;	/* after power of 2 and scales */
1820 		image->upload_height = upload_height;
1821 		image->paletted = uploaded_paletted;
1822 		image->sl = 0;
1823 		image->sh = 1;
1824 		image->tl = 0;
1825 		image->th = 1;
1826 	}
1827 
1828 	return image;
1829 }
1830 
1831 /*
1832  * ================ GL_LoadWal ================
1833  */
1834 image_t        *
GL_LoadWal(char * name)1835 GL_LoadWal(char *name)
1836 {
1837 	miptex_t       *mt;
1838 	int		width, height, ofs;
1839 	image_t        *image;
1840 
1841 	ri.FS_LoadFile(name, (void **)&mt);
1842 	if (!mt) {
1843 		ri.Con_Printf(PRINT_ALL, "GL_FindImage: can't load %s\n", name);
1844 		return r_notexture;
1845 	}
1846 	width = LittleLong(mt->width);
1847 	height = LittleLong(mt->height);
1848 	ofs = LittleLong(mt->offsets[0]);
1849 
1850 
1851 	image = GL_LoadPic(name, (byte *) mt + ofs, width, height, it_wall, 8);
1852 
1853 	ri.FS_FreeFile((void *)mt);
1854 
1855 	return image;
1856 }
1857 
1858 /*
1859  * =============== GL_FindImage
1860  *
1861  * Finds or loads the given image ===============
1862  */
1863 #define IMAGETYPES 3
1864 char           *image_types[IMAGETYPES] = {
1865 	".png",
1866 	".tga",
1867 	".jpg"
1868 };
1869 
1870 image_t        *
GL_FindImage(char * name,imagetype_t type)1871 GL_FindImage(char *name, imagetype_t type)
1872 {
1873 	image_t        *image;
1874 	int		i, len;
1875 	byte           *pic, *palette;
1876 	int		width, height;
1877 	char           *ptr;
1878 
1879 	if (!name)
1880 		return NULL;
1881 		/* ri.Sys_Error (ERR_DROP, "GL_FindImage: NULL name"); */
1882 	len = strlen(name);
1883 	if (len < 5)
1884 		return NULL;
1885 		/* ri.Sys_Error (ERR_DROP, "GL_FindImage: bad name: %s", name); */
1886 
1887 	/* fix backslashes */
1888 	while ((ptr=strchr(name,'\\'))) {
1889 	        *ptr = '/';
1890 	}
1891 
1892 	/* look for it */
1893 	for (i = 0, image = gltextures; i < numgltextures; i++, image++) {
1894 		if (!strcmp(name, image->name)) {
1895 			image->registration_sequence = registration_sequence;
1896 			return image;
1897 		}
1898 	}
1899 
1900 	/* load the pic from disk */
1901 	pic = NULL;
1902 	palette = NULL;
1903 	image = NULL;
1904 	if (!strcmp(name + len - 4, ".pcx")) {
1905 		char		basename[MAX_QPATH];
1906 
1907 		Com_sprintf(basename, sizeof(basename), "%s", name);
1908 		basename[strlen(basename) - 4] = 0;
1909 
1910 		/*
1911 		 * only try to overwrite pcxs, others are specified in model
1912 		 * files etc
1913 		 */
1914 		for (i = 0; i < IMAGETYPES && !image; i++)
1915 			image = GL_FindImage(va("%s%s", basename, image_types[i]), type);
1916 
1917 		if (!image) {
1918 			LoadPCX(name, &pic, &palette, &width, &height);
1919 			if (!pic)
1920 				return NULL;	/* ri.Sys_Error (ERR_DROP, "GL_FindImage: can't load %s", name); */
1921 			image = GL_LoadPic(name, pic, width, height, type, 8);
1922 		}
1923 	} else if (!strcmp(name + len - 4, ".wal")) {
1924 		char		basename[MAX_QPATH];
1925 
1926 		Com_sprintf(basename, sizeof(basename), "%s", name);
1927 		basename[strlen(basename) - 4] = 0;
1928 
1929 		/* only try to overwrite pcxs, others are specified in model files etc */
1930 		for (i = 0; i < IMAGETYPES && !image; i++)
1931 			image = GL_FindImage(va("%s%s", basename, image_types[i]), type);
1932 
1933 		if (!image) {
1934 			image = GL_LoadWal(name);
1935 		}
1936 	} else {
1937 		if (!strcmp(name + len - 4, ".png")) {	/* heffo hax0r */
1938 			LoadPNG(name, &pic, &width, &height);
1939 			if (!pic)
1940 				return NULL;
1941 				/* ri.Sys_Error (ERR_DROP, "GL_FindImage: can't load %s", name); */
1942 			image = GL_LoadPic(name, pic, width, height, type, 32);
1943 		} else if (!strcmp(name + len - 4, ".tga")) {
1944 			LoadTGA(name, &pic, &width, &height);
1945 			if (!pic)
1946 				return NULL;
1947 				/* ri.Sys_Error (ERR_DROP, "GL_FindImage: can't load %s", name); */
1948 			image = GL_LoadPic(name, pic, width, height, type, 32);
1949 		} else if (!strcmp(name + len - 4, ".jpg")) {
1950 			LoadJPG(name, &pic, &width, &height);
1951 			if (!pic)
1952 				return NULL;
1953 				/* ri.Sys_Error (ERR_DROP, "GL_FindImage: can't load %s", name); */
1954 			image = GL_LoadPic(name, pic, width, height, type, 32);
1955 		} else
1956 			return NULL;
1957 			/* ri.Sys_Error (ERR_DROP, "GL_FindImage: bad extension on: %s", name); */
1958 	}
1959 
1960 	if (pic)
1961 		free(pic);
1962 	if (palette)
1963 		free(palette);
1964 	return image;
1965 }
1966 
1967 /*
1968  * =============== R_RegisterSkin ===============
1969  */
1970 struct image_s *
R_RegisterSkin(char * name)1971 R_RegisterSkin(char *name)
1972 {
1973 	return GL_FindImage(name, it_skin);
1974 }
1975 
1976 /*
1977  * ================ GL_FreeUnusedImages
1978  *
1979  * Any image that was not touched on this registration sequence will be freed.
1980  * ================
1981  */
1982 void
GL_FreeUnusedImages(void)1983 GL_FreeUnusedImages(void)
1984 {
1985 	int		i;
1986 	image_t        *image;
1987 
1988 	/* never free r_notexture or particle texture[s] */
1989 	r_notexture->registration_sequence = registration_sequence;
1990 #ifdef QMAX
1991 	r_particlebeam->registration_sequence = registration_sequence;
1992 #else
1993 	r_particletexture->registration_sequence = registration_sequence;
1994 #endif
1995 	/* MH - detail textures begin */
1996 	/* never free detail texture */
1997 	r_detailtexture->registration_sequence = registration_sequence;
1998 	/* MH - detail textures end */
1999 	r_shelltexture->registration_sequence = registration_sequence;	/* c14 added shell texture */
2000 	r_radarmap->registration_sequence = registration_sequence;
2001 	r_around->registration_sequence = registration_sequence;
2002 	r_lblendimage->registration_sequence = registration_sequence;
2003 	r_caustictexture->registration_sequence = registration_sequence;
2004 	r_bholetexture->registration_sequence = registration_sequence;
2005 #ifdef QMAX
2006 	for (i = 0; i < PARTICLE_TYPES; i++)
2007 		if (r_particletextures[i])	/* dont mess with null ones silly :p */
2008 			r_particletextures[i]->registration_sequence = registration_sequence;
2009 #endif
2010 
2011 	for (i = 0, image = gltextures; i < numgltextures; i++, image++) {
2012 		if (image->registration_sequence == registration_sequence)
2013 			continue;	/* used this sequence */
2014 		if (!image->registration_sequence)
2015 			continue;	/* free image_t slot */
2016 		if (image->type == it_pic)
2017 			continue;	/* don't free pics */
2018 		/* free it */
2019 		qglDeleteTextures(1, (GLuint *)&image->texnum);
2020 		memset(image, 0, sizeof(*image));
2021 	}
2022 }
2023 
2024 
2025 /*
2026  * =============== Draw_GetPalette ===============
2027  */
2028 #ifndef QMAX
2029 byte		default_pal[768] = {
2030 
2031 	0, 0, 0, 15, 15, 15, 31, 31, 31, 47, 47, 47,
2032 	63, 63, 63, 75, 75, 75, 91, 91, 91, 107, 107, 107,
2033 	123, 123, 123, 139, 139, 139, 155, 155, 155, 171, 171, 171,
2034 	187, 187, 187, 203, 203, 203, 219, 219, 219, 235, 235, 235,
2035 	99, 75, 35, 91, 67, 31, 83, 63, 31, 79, 59, 27,
2036 	71, 55, 27, 63, 47, 23, 59, 43, 23, 51, 39, 19,
2037 	47, 35, 19, 43, 31, 19, 39, 27, 15, 35, 23, 15,
2038 	27, 19, 11, 23, 15, 11, 19, 15, 7, 15, 11, 7,
2039 	95, 95, 111, 91, 91, 103, 91, 83, 95, 87, 79, 91,
2040 	83, 75, 83, 79, 71, 75, 71, 63, 67, 63, 59, 59,
2041 	59, 55, 55, 51, 47, 47, 47, 43, 43, 39, 39, 39,
2042 	35, 35, 35, 27, 27, 27, 23, 23, 23, 19, 19, 19,
2043 	143, 119, 83, 123, 99, 67, 115, 91, 59, 103, 79, 47,
2044 	207, 151, 75, 167, 123, 59, 139, 103, 47, 111, 83, 39,
2045 	235, 159, 39, 203, 139, 35, 175, 119, 31, 147, 99, 27,
2046 	119, 79, 23, 91, 59, 15, 63, 39, 11, 35, 23, 7,
2047 	167, 59, 43, 159, 47, 35, 151, 43, 27, 139, 39, 19,
2048 	127, 31, 15, 115, 23, 11, 103, 23, 7, 87, 19, 0,
2049 	75, 15, 0, 67, 15, 0, 59, 15, 0, 51, 11, 0,
2050 	43, 11, 0, 35, 11, 0, 27, 7, 0, 19, 7, 0,
2051 	123, 95, 75, 115, 87, 67, 107, 83, 63, 103, 79, 59,
2052 	95, 71, 55, 87, 67, 51, 83, 63, 47, 75, 55, 43,
2053 	67, 51, 39, 63, 47, 35, 55, 39, 27, 47, 35, 23,
2054 	39, 27, 19, 31, 23, 15, 23, 15, 11, 15, 11, 7,
2055 	111, 59, 23, 95, 55, 23, 83, 47, 23, 67, 43, 23,
2056 	55, 35, 19, 39, 27, 15, 27, 19, 11, 15, 11, 7,
2057 	179, 91, 79, 191, 123, 111, 203, 155, 147, 215, 187, 183,
2058 	203, 215, 223, 179, 199, 211, 159, 183, 195, 135, 167, 183,
2059 	115, 151, 167, 91, 135, 155, 71, 119, 139, 47, 103, 127,
2060 	23, 83, 111, 19, 75, 103, 15, 67, 91, 11, 63, 83,
2061 	7, 55, 75, 7, 47, 63, 7, 39, 51, 0, 31, 43,
2062 	0, 23, 31, 0, 15, 19, 0, 7, 11, 0, 0, 0,
2063 	139, 87, 87, 131, 79, 79, 123, 71, 71, 115, 67, 67,
2064 	107, 59, 59, 99, 51, 51, 91, 47, 47, 87, 43, 43,
2065 	75, 35, 35, 63, 31, 31, 51, 27, 27, 43, 19, 19,
2066 	31, 15, 15, 19, 11, 11, 11, 7, 7, 0, 0, 0,
2067 	151, 159, 123, 143, 151, 115, 135, 139, 107, 127, 131, 99,
2068 	119, 123, 95, 115, 115, 87, 107, 107, 79, 99, 99, 71,
2069 	91, 91, 67, 79, 79, 59, 67, 67, 51, 55, 55, 43,
2070 	47, 47, 35, 35, 35, 27, 23, 23, 19, 15, 15, 11,
2071 	159, 75, 63, 147, 67, 55, 139, 59, 47, 127, 55, 39,
2072 	119, 47, 35, 107, 43, 27, 99, 35, 23, 87, 31, 19,
2073 	79, 27, 15, 67, 23, 11, 55, 19, 11, 43, 15, 7,
2074 	31, 11, 7, 23, 7, 0, 11, 0, 0, 0, 0, 0,
2075 	119, 123, 207, 111, 115, 195, 103, 107, 183, 99, 99, 167,
2076 	91, 91, 155, 83, 87, 143, 75, 79, 127, 71, 71, 115,
2077 	63, 63, 103, 55, 55, 87, 47, 47, 75, 39, 39, 63,
2078 	35, 31, 47, 27, 23, 35, 19, 15, 23, 11, 7, 7,
2079 	155, 171, 123, 143, 159, 111, 135, 151, 99, 123, 139, 87,
2080 	115, 131, 75, 103, 119, 67, 95, 111, 59, 87, 103, 51,
2081 	75, 91, 39, 63, 79, 27, 55, 67, 19, 47, 59, 11,
2082 	35, 47, 7, 27, 35, 0, 19, 23, 0, 11, 15, 0,
2083 	0, 255, 0, 35, 231, 15, 63, 211, 27, 83, 187, 39,
2084 	95, 167, 47, 95, 143, 51, 95, 123, 51, 255, 255, 255,
2085 	255, 255, 211, 255, 255, 167, 255, 255, 127, 255, 255, 83,
2086 	255, 255, 39, 255, 235, 31, 255, 215, 23, 255, 191, 15,
2087 	255, 171, 7, 255, 147, 0, 239, 127, 0, 227, 107, 0,
2088 	211, 87, 0, 199, 71, 0, 183, 59, 0, 171, 43, 0,
2089 	155, 31, 0, 143, 23, 0, 127, 15, 0, 115, 7, 0,
2090 	95, 0, 0, 71, 0, 0, 47, 0, 0, 27, 0, 0,
2091 	239, 0, 0, 55, 55, 255, 255, 0, 0, 0, 0, 255,
2092 	43, 43, 35, 27, 27, 23, 19, 19, 15, 235, 151, 127,
2093 	195, 115, 83, 159, 87, 51, 123, 63, 27, 235, 211, 199,
2094 	199, 171, 155, 167, 139, 119, 135, 107, 87, 159, 91, 83
2095 };
2096 #endif
2097 
2098 int
Draw_GetPalette(void)2099 Draw_GetPalette(void)
2100 {
2101 	int		i;
2102 	int		r, g, b;
2103 	unsigned	v;
2104 	byte           *pic, *pal;
2105 	int		width, height;
2106 #ifndef QMAX
2107 	byte		default_pal[768];
2108 #endif
2109 
2110 	/* get the palette */
2111 
2112 	LoadPCX("pics/colormap.pcx", &pic, &pal, &width, &height);
2113 	if (!pal) {
2114 		ri.Sys_Error(ERR_FATAL, "Couldn't load pics/colormap.pcx");
2115 	} else
2116 		for (i = 0; i < 256; i++) {
2117 			r = pal[i * 3 + 0];
2118 			g = pal[i * 3 + 1];
2119 			b = pal[i * 3 + 2];
2120 
2121 			v = (255 << 24) + (r << 0) + (g << 8) + (b << 16);
2122 			d_8to24table[i] = LittleLong(v);
2123 #ifndef QMAX
2124 			d_8to24tablef[i][0] = r * 0.003921568627450980392156862745098;
2125 			d_8to24tablef[i][1] = g * 0.003921568627450980392156862745098;
2126 			d_8to24tablef[i][2] = b * 0.003921568627450980392156862745098;
2127 #endif
2128 		}
2129 
2130 	d_8to24table[255] &= LittleLong(0xffffff);	/* 255 is transparent */
2131 
2132 #ifdef QMAX
2133 	free(pic);
2134 	free(pal);
2135 #else
2136 	if (pic)
2137 		free(pic);
2138 	if (pal != default_pal)
2139 		free(pal);
2140 #endif
2141 
2142 	return 0;
2143 }
2144 
2145 
2146 /*
2147  * =============== GL_InitImages ===============
2148  */
2149 void
GL_InitImages(void)2150 GL_InitImages(void)
2151 {
2152 	int		i, j;
2153 	float		g = vid_gamma->value;
2154 
2155 	registration_sequence = 1;
2156 
2157 	/* init intensity conversions */
2158 	/* Vic - begin */
2159 	if (gl_config.mtexcombine)
2160 		intensity = ri.Cvar_Get("intensity", "1.5", CVAR_ARCHIVE);
2161 	else
2162 		intensity = ri.Cvar_Get("intensity", "2", CVAR_ARCHIVE);
2163 	/* Vic - end */
2164 
2165 	if (intensity->value <= 1)
2166 		ri.Cvar_Set("intensity", "1");
2167 
2168 	gl_state.inverse_intensity = 1 / intensity->value;
2169 
2170 	Draw_GetPalette();
2171 
2172 	if (qglColorTableEXT) {
2173 		ri.FS_LoadFile("pics/16to8.dat",
2174 		    (void **)&gl_state.d_16to8table);
2175 		if (!gl_state.d_16to8table)
2176 			ri.Sys_Error(ERR_FATAL, "Couldn't load pics/16to8.pcx");
2177 	}
2178 	if (gl_config.renderer & (GL_RENDERER_VOODOO | GL_RENDERER_VOODOO2)) {
2179 		g = 1.0;
2180 	}
2181 	for (i = 0; i < 256; i++) {
2182 		if (g == 1 || gl_state.hwgamma) {
2183 			gammatable[i] = i;
2184 		} else {
2185 			float		inf;
2186 
2187 			inf = 255 * pow((i + 0.5) * DIV255, g) + 0.5;
2188 			if (inf < 0)
2189 				inf = 0;
2190 			if (inf > 255)
2191 				inf = 255;
2192 			gammatable[i] = inf;
2193 		}
2194 	}
2195 
2196 	for (i = 0; i < 256; i++) {
2197 		j = i * intensity->value;
2198 		if (j > 255)
2199 			j = 255;
2200 		intensitytable[i] = j;
2201 	}
2202 
2203 	R_InitBloomTextures();		/* BLOOMS */
2204 }
2205 
2206 /*
2207  * =============== GL_ShutdownImages ===============
2208  */
2209 void
GL_ShutdownImages(void)2210 GL_ShutdownImages(void)
2211 {
2212 	int		i;
2213 	image_t        *image;
2214 
2215 	for (i = 0, image = gltextures; i < numgltextures; i++, image++) {
2216 		if (!image->registration_sequence)
2217 			continue;	/* free image_t slot */
2218 		/* free it */
2219 		qglDeleteTextures(1, (GLuint *)&image->texnum);
2220 		memset(image, 0, sizeof(*image));
2221 	}
2222 }
2223