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 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 // for jpeglib
26 #define HAVE_PROTOTYPES
27 
28 #include "r_local.h"
29 
30 #if defined HAVE_JPEG_JPEGLIB_H
31 #include "jpeg/jpeglib.h"
32 #else
33 #include "jpeglib.h"
34 #endif
35 
36 image_t		gltextures[MAX_GLTEXTURES];
37 image_t		*r_mirrortexture;
38 image_t		*r_depthtexture;
39 image_t		*r_depthtexture2;
40 int			numgltextures;
41 int			base_textureid;		// gltextures[i] = base_textureid+i
42 
43 extern cvar_t	*cl_hudimage1; //custom huds
44 extern cvar_t	*cl_hudimage2;
45 
46 unsigned	d_8to24table[256];
47 
48 qboolean GL_Upload8 (byte *data, int width, int height, int picmip, qboolean filter);
49 qboolean GL_Upload32 (byte *data, int width, int height, int picmip, qboolean filter, qboolean force_standard_mipmap);
50 
51 int		gl_solid_format = 3;
52 int		gl_alpha_format = 4;
53 
54 int		gl_tex_solid_format = 3;
55 int		gl_tex_alpha_format = 4;
56 
57 int		gl_filter_min = GL_LINEAR_MIPMAP_LINEAR;
58 int		gl_filter_max = GL_LINEAR;
59 
R_InitImageSubsystem(void)60 void R_InitImageSubsystem(void)
61 {
62 	int		max_aniso;
63 
64 	if ( strstr( gl_config.extensions_string, "GL_ARB_multitexture" ) )
65 	{
66 		Com_Printf ("...using GL_ARB_multitexture\n" );
67 		qglMTexCoord2fARB = ( void * ) qwglGetProcAddress( "glMultiTexCoord2fARB" );
68 		qglMTexCoord3fARB = ( void * ) qwglGetProcAddress( "glMultiTexCoord3fARB" );
69 		qglMultiTexCoord3fvARB = (void*)qwglGetProcAddress("glMultiTexCoord3fvARB");
70 		qglActiveTextureARB = ( void * ) qwglGetProcAddress( "glActiveTextureARB" );
71 		qglClientActiveTextureARB = ( void * ) qwglGetProcAddress( "glClientActiveTextureARB" );
72 		GL_TEXTURE0 = GL_TEXTURE0_ARB;
73 		GL_TEXTURE1 = GL_TEXTURE1_ARB;
74 		GL_TEXTURE2 = GL_TEXTURE2_ARB;
75 		GL_TEXTURE3 = GL_TEXTURE3_ARB;
76 		GL_TEXTURE4 = GL_TEXTURE4_ARB;
77 		GL_TEXTURE5 = GL_TEXTURE5_ARB;
78 		GL_TEXTURE6 = GL_TEXTURE6_ARB;
79 		GL_TEXTURE7 = GL_TEXTURE7_ARB;
80 	}
81 	else
82 	{
83 		Com_Error (ERR_FATAL, "...GL_ARB_multitexture not found\n" );
84 	}
85 
86 	gl_config.mtexcombine = false;
87 	if ( strstr( gl_config.extensions_string, "GL_ARB_texture_env_combine" ) )
88 	{
89 		Com_Printf( "...using GL_ARB_texture_env_combine\n" );
90 		gl_config.mtexcombine = true;
91 	}
92 	else
93 	{
94 		Com_Printf( "...GL_ARB_texture_env_combine not found\n" );
95 	}
96 	if ( !gl_config.mtexcombine )
97 	{
98 		if ( strstr( gl_config.extensions_string, "GL_EXT_texture_env_combine" ) )
99 		{
100 			Com_Printf( "...using GL_EXT_texture_env_combine\n" );
101 			gl_config.mtexcombine = true;
102 		}
103 		else
104 		{
105 			Com_Printf( "...GL_EXT_texture_env_combine not found\n" );
106 		}
107 	}
108 
109 	if (strstr(gl_config.extensions_string, "GL_EXT_texture_filter_anisotropic"))
110 	{
111 		qglGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_aniso);
112 
113 		r_ext_max_anisotropy = Cvar_Get("r_ext_max_anisotropy", "1", CVAR_ARCHIVE );
114 		Cvar_SetValue("r_ext_max_anisotropy", max_aniso);
115 
116 		r_anisotropic = Cvar_Get("r_anisotropic", "1", CVAR_ARCHIVE);
117 		if (r_anisotropic->integer >= r_ext_max_anisotropy->integer)
118 			Cvar_SetValue("r_anisotropic", r_ext_max_anisotropy->integer);
119 		if (r_anisotropic->integer <= 0)
120 			Cvar_SetValue("r_anisotropic", 1);
121 
122 		r_alphamasked_anisotropic = Cvar_Get("r_alphamasked_anisotropic", "1", CVAR_ARCHIVE);
123 		if (r_alphamasked_anisotropic->integer >= r_ext_max_anisotropy->integer)
124 			Cvar_SetValue("r_alphamasked_anisotropic", r_ext_max_anisotropy->integer);
125 		if (r_alphamasked_anisotropic->integer <= 0)
126 			Cvar_SetValue("r_alphamasked_anisotropic", 1);
127 
128 		if (r_anisotropic->integer == 1 && r_alphamasked_anisotropic->integer == 1)
129 			Com_Printf("...ignoring GL_EXT_texture_filter_anisotropic\n");
130 		else
131 			Com_Printf("...using GL_EXT_texture_filter_anisotropic\n");
132 	}
133 	else
134 	{
135 		Com_Printf("...GL_EXT_texture_filter_anisotropic not found\n");
136 		r_anisotropic = Cvar_Get("r_anisotropic", "0", CVAR_ARCHIVE);
137 		r_alphamasked_anisotropic = Cvar_Get("r_alphamasked_anisotropic", "0", CVAR_ARCHIVE);
138 		r_ext_max_anisotropy = Cvar_Get("r_ext_max_anisotropy", "0", CVAR_ARCHIVE);
139 	}
140 }
141 
142 GLenum bFunc1 = -1;
143 GLenum bFunc2 = -1;
GL_BlendFunction(GLenum sfactor,GLenum dfactor)144 void GL_BlendFunction (GLenum sfactor, GLenum dfactor)
145 {
146 	if (sfactor!=bFunc1 || dfactor!=bFunc2)
147 	{
148 		bFunc1 = sfactor;
149 		bFunc2 = dfactor;
150 
151 		qglBlendFunc(bFunc1, bFunc2);
152 	}
153 }
154 
155 GLenum shadeModelMode = -1;
156 
GL_ShadeModel(GLenum mode)157 void GL_ShadeModel (GLenum mode)
158 {
159 	if (mode!=shadeModelMode)
160 	{
161 		shadeModelMode = mode;
162 		qglShadeModel(mode);
163 	}
164 }
165 
166 // FIXME:
167 // This centralized texture bind batching system is a great idea if you use it
168 // *everywhere*. Otherwise you just end up binding a texture elsewhere and
169 // this system doesn't know you've done it, so when you count on this system
170 // to bindanother texture, it doesn't know it has to, and it'll happily let
171 // you use the wrong texture. Anywhere we use glActiveTexture and
172 // glBindTexture directly can potentially screw things up.
173 
GL_EnableMultitexture(qboolean enable)174 void GL_EnableMultitexture( qboolean enable )
175 {
176 	if ( !qglActiveTextureARB )
177 		return;
178 
179 	if ( enable )
180 	{
181 		GL_SelectTexture( GL_TEXTURE1 );
182 		qglEnable( GL_TEXTURE_2D );
183 		GL_TexEnv( GL_REPLACE );
184 
185 		GL_SelectTexture( GL_TEXTURE2 );
186 		qglEnable( GL_TEXTURE_2D );
187 		GL_TexEnv( GL_REPLACE );
188 
189 		GL_SelectTexture( GL_TEXTURE3 );
190 		qglEnable( GL_TEXTURE_2D );
191 		GL_TexEnv( GL_REPLACE );
192 	}
193 	else
194 	{
195 		GL_SelectTexture( GL_TEXTURE1 );
196 		qglDisable( GL_TEXTURE_2D );
197 		GL_TexEnv( GL_REPLACE );
198 
199 		GL_SelectTexture( GL_TEXTURE2 );
200 		qglDisable( GL_TEXTURE_2D );
201 		GL_TexEnv( GL_REPLACE );
202 
203 		GL_SelectTexture( GL_TEXTURE3 );
204 		qglDisable( GL_TEXTURE_2D );
205 		GL_TexEnv( GL_REPLACE );
206 	}
207 	GL_SelectTexture( GL_TEXTURE0 );
208 	GL_TexEnv( GL_REPLACE );
209 }
210 
GL_SelectTexture(GLenum texture)211 void GL_SelectTexture( GLenum texture )
212 {
213 	int tmu;
214 
215 	if ( !qglActiveTextureARB )
216 		return;
217 
218 	if ( texture == GL_TEXTURE0 )
219 	{
220 		tmu = 0;
221 	}
222 	else
223 	{
224 		tmu = 1;
225 	}
226 
227 	if ( tmu == gl_state.currenttmu )
228 	{
229 		return;
230 	}
231 
232 	gl_state.currenttmu = tmu;
233 
234 	if ( qglActiveTextureARB )
235 	{
236 		qglActiveTextureARB( texture );
237 		qglClientActiveTextureARB( texture );
238 	}
239 }
240 
GL_TexEnv(GLenum mode)241 void GL_TexEnv( GLenum mode )
242 {
243 	static int lastmodes[2] = { -1, -1 };
244 
245 	if ( mode != lastmodes[gl_state.currenttmu] )
246 	{
247 		qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode );
248 		lastmodes[gl_state.currenttmu] = mode;
249 	}
250 }
251 
GL_Bind(int texnum)252 void GL_Bind (int texnum)
253 {
254 	extern	image_t	*draw_chars;
255 
256 	if (gl_nobind->integer && draw_chars)		// performance evaluation option
257 		texnum = draw_chars->texnum;
258 	if ( gl_state.currenttextures[gl_state.currenttmu] == texnum)
259 		return;
260 	gl_state.currenttextures[gl_state.currenttmu] = texnum;
261 	qglBindTexture (GL_TEXTURE_2D, texnum);
262 }
263 
GL_MBind(GLenum target,int texnum)264 void GL_MBind( GLenum target, int texnum )
265 {
266 	GL_SelectTexture( target );
267 	if ( target == GL_TEXTURE0 )
268 	{
269 		if ( gl_state.currenttextures[0] == texnum )
270 			return;
271 	}
272 	else
273 	{
274 		if ( gl_state.currenttextures[1] == texnum )
275 			return;
276 	}
277 	GL_Bind( texnum );
278 }
279 
280 typedef struct
281 {
282 	char *name;
283 	int	minimize, maximize;
284 } glmode_t;
285 
286 glmode_t modes[] = {
287 	{"GL_NEAREST", GL_NEAREST, GL_NEAREST},
288 	{"GL_LINEAR", GL_LINEAR, GL_LINEAR},
289 	{"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
290 	{"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
291 	{"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
292 	{"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
293 };
294 
295 #define NUM_GL_MODES (sizeof(modes) / sizeof (glmode_t))
296 
297 typedef struct
298 {
299 	char *name;
300 	int mode;
301 } gltmode_t;
302 
303 gltmode_t gl_alpha_modes[] = {
304 	{"default", 4},
305 	{"GL_RGBA", GL_RGBA},
306 	{"GL_RGBA8", GL_RGBA8},
307 	{"GL_RGB5_A1", GL_RGB5_A1},
308 	{"GL_RGBA4", GL_RGBA4},
309 	{"GL_RGBA2", GL_RGBA2},
310 };
311 
312 #define NUM_GL_ALPHA_MODES (sizeof(gl_alpha_modes) / sizeof (gltmode_t))
313 
314 gltmode_t gl_solid_modes[] = {
315 	{"default", 3},
316 	{"GL_RGB", GL_RGB},
317 	{"GL_RGB8", GL_RGB8},
318 	{"GL_RGB5", GL_RGB5},
319 	{"GL_RGB4", GL_RGB4},
320 	{"GL_R3_G3_B2", GL_R3_G3_B2},
321 #ifdef GL_RGB2_EXT
322 	{"GL_RGB2", GL_RGB2_EXT},
323 #endif
324 };
325 
326 #define NUM_GL_SOLID_MODES (sizeof(gl_solid_modes) / sizeof (gltmode_t))
327 
328 /*
329 ===============
330 GL_TextureMode
331 ===============
332 */
GL_TextureMode(char * string)333 void GL_TextureMode( char *string )
334 {
335 	int		i;
336 	image_t	*glt;
337 
338 	for (i=0 ; i< NUM_GL_MODES ; i++)
339 	{
340 		if ( !Q_strcasecmp( modes[i].name, string ) )
341 			break;
342 	}
343 
344 	if (i == NUM_GL_MODES)
345 	{
346 		Com_Printf ("bad filter name\n");
347 		return;
348 	}
349 
350 	gl_filter_min = modes[i].minimize;
351 	gl_filter_max = modes[i].maximize;
352 
353 	// change all the existing mipmap texture objects
354 	for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
355 	{
356 		if (glt->type != it_pic && glt->type != it_particle && glt->type != it_sky )
357 		{
358 			GL_Bind (glt->texnum);
359 			qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
360 			qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
361 		}
362 	}
363 }
364 
365 /*
366 ===============
367 GL_TextureAlphaMode
368 ===============
369 */
GL_TextureAlphaMode(char * string)370 void GL_TextureAlphaMode( char *string )
371 {
372 	int		i;
373 
374 	for (i=0 ; i< NUM_GL_ALPHA_MODES ; i++)
375 	{
376 		if ( !Q_strcasecmp( gl_alpha_modes[i].name, string ) )
377 			break;
378 	}
379 
380 	if (i == NUM_GL_ALPHA_MODES)
381 	{
382 		Com_Printf ("bad alpha texture mode name\n");
383 		return;
384 	}
385 
386 	gl_tex_alpha_format = gl_alpha_modes[i].mode;
387 }
388 
389 /*
390 ===============
391 GL_TextureSolidMode
392 ===============
393 */
GL_TextureSolidMode(char * string)394 void GL_TextureSolidMode( char *string )
395 {
396 	int		i;
397 
398 	for (i=0 ; i< NUM_GL_SOLID_MODES ; i++)
399 	{
400 		if ( !Q_strcasecmp( gl_solid_modes[i].name, string ) )
401 			break;
402 	}
403 
404 	if (i == NUM_GL_SOLID_MODES)
405 	{
406 		Com_Printf ("bad solid texture mode name\n");
407 		return;
408 	}
409 
410 	gl_tex_solid_format = gl_solid_modes[i].mode;
411 }
412 
413 /*
414 ===============
415 GL_ImageList_f
416 ===============
417 */
GL_ImageList_f(void)418 void	GL_ImageList_f (void)
419 {
420 	int		i;
421 	image_t	*image;
422 	int		texels;
423 	const char *palstrings[2] =
424 	{
425 		"RGB",
426 		"PAL"
427 	};
428 
429 	Com_Printf ("------------------\n");
430 	texels = 0;
431 
432 	for (i=0, image=gltextures ; i<numgltextures ; i++, image++)
433 	{
434 		if (image->texnum <= 0)
435 			continue;
436 		texels += image->upload_width*image->upload_height;
437 		switch (image->type)
438 		{
439 		case it_skin:
440 			Com_Printf ("M");
441 			break;
442 		case it_sprite:
443 			Com_Printf ("S");
444 			break;
445 		case it_wall:
446 			Com_Printf ("W");
447 			break;
448 		case it_pic:
449 			Com_Printf ("P");
450 			break;
451 		case it_particle:
452 			Com_Printf ("A");
453 			break;
454 		default:
455 			Com_Printf (" ");
456 			break;
457 		}
458 
459 		Com_Printf (" %3i %3i %s: %s\n",
460 			image->upload_width, image->upload_height, palstrings[image->paletted], image->name);
461 	}
462 	Com_Printf ("Total texel count (not counting mipmaps): %i\n", texels);
463 }
464 
465 
466 /*
467 =============================================================================
468 
469   scrap allocation
470 
471   Allocate all the little status bar obejcts into a single texture
472   to crutch up inefficient hardware / drivers
473 
474 =============================================================================
475 */
476 
477 #define	MAX_SCRAPS		1
478 #define	BLOCK_WIDTH		1024
479 #define	BLOCK_HEIGHT	512
480 
481 int			scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH];
482 byte		scrap_texels[MAX_SCRAPS][BLOCK_WIDTH*BLOCK_HEIGHT*4];
483 qboolean	scrap_dirty;
484 
485 // returns a texture number and the position inside it
Scrap_AllocBlock(int w,int h,int * x,int * y)486 int Scrap_AllocBlock (int w, int h, int *x, int *y)
487 {
488 	int		i, j;
489 	int		best, best2;
490 	int		texnum;
491 
492 	for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++)
493 	{
494 		best = BLOCK_HEIGHT;
495 
496 		for (i=0 ; i<BLOCK_WIDTH-w ; i++)
497 		{
498 			best2 = 0;
499 
500 			for (j=0 ; j<w ; j++)
501 			{
502 				if (scrap_allocated[texnum][i+j] >= best)
503 					break;
504 				if (scrap_allocated[texnum][i+j] > best2)
505 					best2 = scrap_allocated[texnum][i+j];
506 			}
507 			if (j == w)
508 			{	// this is a valid spot
509 				*x = i;
510 				*y = best = best2;
511 			}
512 		}
513 
514 		if (best + h > BLOCK_HEIGHT)
515 			continue;
516 
517 		for (i=0 ; i<w ; i++)
518 			scrap_allocated[texnum][*x + i] = best + h;
519 
520 		return texnum;
521 	}
522 
523 	return -1;
524 /*	Sys_Error ("Scrap_AllocBlock: full");*/
525 }
526 
527 int	scrap_uploads;
528 
Scrap_Upload(void)529 void Scrap_Upload (void)
530 {
531 	GL_Bind(TEXNUM_SCRAPS);
532 	GL_Upload32 (scrap_texels[scrap_uploads++], BLOCK_WIDTH, BLOCK_HEIGHT, 0, false, true);
533 	scrap_dirty = false;
534 }
535 
536 //just a guessed size-- this isn't necessarily raw RGBA data, it's the
537 //encoded image data.
538 #define	STATIC_RAWDATA_SIZE	(1024*1024*4+256)
539 byte	static_rawdata[STATIC_RAWDATA_SIZE];
540 
541 /*
542 =================================================================
543 
544 PCX LOADING
545 
546 =================================================================
547 */
548 
549 
550 /*
551 ==============
552 LoadPCX
553 ==============
554 */
LoadPCX(char * filename,byte ** pic,byte ** palette,int * width,int * height)555 void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height)
556 {
557 	byte	*raw;
558 	pcx_t	*pcx;
559 	int		x, y;
560 	int		len;
561 	int		dataByte, runLength;
562 	byte	*out, *pix;
563 
564 	*pic = NULL;
565 	*palette = NULL;
566 
567 	//
568 	// load the file
569 	//
570 	len = FS_LoadFile_TryStatic (	filename, (void **)&raw, static_rawdata,
571 									STATIC_RAWDATA_SIZE);
572 	if (!raw)
573 	{
574 		return;
575 	}
576 
577 	//
578 	// parse the PCX file
579 	//
580 	pcx = (pcx_t *)raw;
581 
582     pcx->xmin = LittleShort(pcx->xmin);
583     pcx->ymin = LittleShort(pcx->ymin);
584     pcx->xmax = LittleShort(pcx->xmax);
585     pcx->ymax = LittleShort(pcx->ymax);
586     pcx->hres = LittleShort(pcx->hres);
587     pcx->vres = LittleShort(pcx->vres);
588     pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
589     pcx->palette_type = LittleShort(pcx->palette_type);
590 
591 	raw = &pcx->data;
592 
593 	if (pcx->manufacturer != 0x0a
594 		|| pcx->version != 5
595 		|| pcx->encoding != 1
596 		|| pcx->bits_per_pixel != 8
597 		|| pcx->xmax >= 1024
598 		|| pcx->ymax >= 512)
599 	{
600 		Com_Printf ("Bad pcx file %s\n", filename);
601 		if ((byte *)pcx != static_rawdata)
602 			FS_FreeFile (pcx);
603 		return;
604 	}
605 
606 	out = malloc ( (pcx->ymax+1) * (pcx->xmax+1) );
607 
608 	*pic = out;
609 
610 	pix = out;
611 
612 	if (palette)
613 	{
614 		*palette = malloc(768);
615 		memcpy (*palette, (byte *)pcx + len - 768, 768);
616 	}
617 
618 	if (width)
619 		*width = pcx->xmax+1;
620 	if (height)
621 		*height = pcx->ymax+1;
622 
623 	for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1)
624 	{
625 		for (x=0 ; x<=pcx->xmax ; )
626 		{
627 			dataByte = *raw++;
628 
629 			if ((dataByte & 0xC0) == 0xC0)
630 			{
631 				runLength = dataByte & 0x3F;
632 				dataByte = *raw++;
633 			}
634 			else
635 				runLength = 1;
636 
637 			while (runLength-- > 0)
638 				pix[x++] = dataByte;
639 		}
640 
641 	}
642 
643 	if ( raw - (byte *)pcx > len)
644 	{
645 		Com_DPrintf ("PCX file %s was malformed", filename);
646 		free (*pic);
647 		*pic = NULL;
648 	}
649 
650 	if ((byte *)pcx != static_rawdata)
651 		FS_FreeFile (pcx);
652 }
653 /*
654 =================================================================
655 
656 JPEG LOADING
657 
658 By Robert 'Heffo' Heffernan
659 
660 =================================================================
661 */
662 
663 static JOCTET eoi_buffer[2] = {(JOCTET)0xFF, (JOCTET)JPEG_EOI};
664 static qboolean crjpg_corrupted;
665 
crjpg_null(j_decompress_ptr cinfo)666 void crjpg_null(j_decompress_ptr cinfo)
667 {
668 }
669 
crjpg_fill_input_buffer(j_decompress_ptr cinfo)670 int crjpg_fill_input_buffer(j_decompress_ptr cinfo)
671 {
672     Com_Printf("Premature end of JPEG data\n");
673     cinfo->src->next_input_byte = eoi_buffer;
674     cinfo->src->bytes_in_buffer = 2;
675     crjpg_corrupted = true;
676     return 1;
677 }
678 
crjpg_skip_input_data(j_decompress_ptr cinfo,long num_bytes)679 void crjpg_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
680 {
681 
682     cinfo->src->next_input_byte += (size_t) num_bytes;
683     cinfo->src->bytes_in_buffer -= (size_t) num_bytes;
684 
685     if (cinfo->src->bytes_in_buffer < 0)
686     {
687 		Com_Printf("Premature end of JPEG data\n");
688 		cinfo->src->next_input_byte = eoi_buffer;
689     	cinfo->src->bytes_in_buffer = 2;
690     	crjpg_corrupted = true;
691     }
692 }
693 
crjpg_mem_src(j_decompress_ptr cinfo,byte * mem,int len)694 void crjpg_mem_src(j_decompress_ptr cinfo, byte *mem, int len)
695 {
696     cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small)((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(struct jpeg_source_mgr));
697     cinfo->src->init_source = crjpg_null;
698     cinfo->src->fill_input_buffer = crjpg_fill_input_buffer;
699     cinfo->src->skip_input_data = crjpg_skip_input_data;
700     cinfo->src->resync_to_restart = jpeg_resync_to_restart;
701     cinfo->src->term_source = crjpg_null;
702     cinfo->src->bytes_in_buffer = len;
703     cinfo->src->next_input_byte = mem;
704 }
705 
706 #define DSTATE_START	200	/* after create_decompress */
707 #define DSTATE_INHEADER	201	/* reading header markers, no SOS yet */
708 
709 /*
710 ==============
711 LoadJPG
712 ==============
713 */
714 #define	STATIC_SCANLINE_SIZE	(1024*3)
715 byte	static_scanline[STATIC_SCANLINE_SIZE];
LoadJPG(char * filename,byte ** pic,int * width,int * height)716 void LoadJPG (char *filename, byte **pic, int *width, int *height)
717 {
718 	struct jpeg_decompress_struct	cinfo;
719 	struct jpeg_error_mgr			jerr;
720 	byte							*rawdata, *rgbadata, *scanline, *p, *q;
721 	int								rawsize, i;
722 
723 	crjpg_corrupted = false;
724 	// Load JPEG file into memory
725 	rawsize = FS_LoadFile_TryStatic	(	filename, (void **)&rawdata,
726 										static_rawdata, STATIC_RAWDATA_SIZE);
727 	if (!rawdata)
728 	{
729 		return;
730 	}
731 
732 	// Knightmare- check for bad data
733 	if (	rawdata[6] != 'J'
734 		||	rawdata[7] != 'F'
735 		||	rawdata[8] != 'I'
736 		||	rawdata[9] != 'F') {
737 		if (rawdata != static_rawdata)
738 			FS_FreeFile(rawdata);
739 		return;
740 	}
741 
742 	// Initialise libJpeg Object
743 	cinfo.err = jpeg_std_error(&jerr);
744 	jpeg_create_decompress(&cinfo);
745 
746 	// Feed JPEG memory into the libJpeg Object
747 	crjpg_mem_src(&cinfo, rawdata, rawsize);
748 
749 	// Process JPEG header
750 	jpeg_read_header(&cinfo, true); // bombs out here
751 
752 	// Start Decompression
753 	jpeg_start_decompress(&cinfo);
754 
755 	// Check Color Components
756 	if(cinfo.output_components != 3)
757 	{
758 		jpeg_destroy_decompress(&cinfo);
759 		if (rawdata != static_rawdata)
760 			FS_FreeFile(rawdata);
761 		return;
762 	}
763 
764 	// Allocate Memory for decompressed image
765 	rgbadata = malloc(cinfo.output_width * cinfo.output_height * 4);
766 	if(!rgbadata)
767 	{
768 		jpeg_destroy_decompress(&cinfo);
769 		if (rawdata != static_rawdata)
770 			FS_FreeFile(rawdata);
771 		return;
772 	}
773 
774 	// Pass sizes to output
775 	*width = cinfo.output_width; *height = cinfo.output_height;
776 
777 	// Allocate Scanline buffer
778 	if (cinfo.output_width * 3 < STATIC_SCANLINE_SIZE)
779 	{
780 		scanline = &static_scanline[0];
781 	}
782 	else
783 	{
784 		scanline = malloc(cinfo.output_width * 3);
785 		if(!scanline)
786 		{
787 			free(rgbadata);
788 			jpeg_destroy_decompress(&cinfo);
789 			if (rawdata != static_rawdata)
790 				FS_FreeFile(rawdata);
791 			return;
792 		}
793 	}
794 
795 	// Read Scanlines, and expand from RGB to RGBA
796 	q = rgbadata;
797 	while(cinfo.output_scanline < cinfo.output_height)
798 	{
799 		p = scanline;
800 		jpeg_read_scanlines(&cinfo, &scanline, 1);
801 
802 		for(i=0; i<cinfo.output_width; i++)
803 		{
804 			q[0] = p[0];
805 			q[1] = p[1];
806 			q[2] = p[2];
807 			q[3] = 255;
808 
809 			p+=3; q+=4;
810 		}
811 	}
812 
813 	// Free the scanline buffer
814 	if (scanline != &static_scanline[0])
815 		free(scanline);
816 
817 	// Finish Decompression
818 	jpeg_finish_decompress(&cinfo);
819 
820 	// Destroy JPEG object
821 	jpeg_destroy_decompress(&cinfo);
822 
823 	// Free the raw data now that it's done being processed
824 	if (rawdata != static_rawdata)
825     	FS_FreeFile(rawdata);
826 
827     if (crjpg_corrupted)
828     	Com_Printf ("JPEG file %s is likely corrupted, please obtain a fresh copy.\n", filename);
829 
830 	// Return the 'rgbadata'
831 	*pic = rgbadata;
832 }
833 
834 
835 /*
836 =========================================================
837 
838 TARGA LOADING
839 
840 =========================================================
841 */
842 
843 typedef struct _TargaHeader {
844 	unsigned char 	id_length, colormap_type, image_type;
845 	unsigned short	colormap_index, colormap_length;
846 	unsigned char	colormap_size;
847 	unsigned short	x_origin, y_origin, width, height;
848 	unsigned char	pixel_size, attributes;
849 } TargaHeader;
850 
851 
852 /*
853 =============
854 LoadTGA
855 =============
856 */
LoadTGA(char * name,byte ** pic,int * width,int * height)857 void LoadTGA (char *name, byte **pic, int *width, int *height)
858 {
859 	int		columns, rows, numPixels;
860 	byte	*pixbuf;
861 	int		row, column;
862 	byte	*buf_p;
863 	byte	*buffer;
864 	size_t	buf_end;
865 	int		length;
866 	TargaHeader		targa_header;
867 	byte			*targa_rgba;
868 	byte tmp[2];
869 
870 	*pic = NULL;
871 
872 	//
873 	// load the file
874 	//
875 	length = FS_LoadFile_TryStatic	(	name, (void **)&buffer,
876 										static_rawdata, STATIC_RAWDATA_SIZE);
877 	if (!buffer)
878 	{
879 		return;
880 	}
881 
882 	buf_p = buffer;
883 	buf_end = (size_t)(buffer+length);
884 
885 #define GET_TGA_BYTE(dest) \
886 	{\
887 		if ((size_t)buf_p<buf_end)\
888 		{\
889 			(dest) = *buf_p++;\
890 		}\
891 		else\
892 		{\
893 			/* We don't set *pic to NULL, so if the image is mostly intact,
894 			 * whatever pixels were already there will still show up.
895 			 */\
896 			Com_Printf ("LoadTGA: %s is either truncated or corrupt, please obtain a fresh copy!\n", name);\
897 			return;\
898 		}\
899 	}
900 
901 	GET_TGA_BYTE (targa_header.id_length);
902 	GET_TGA_BYTE (targa_header.colormap_type);
903 	GET_TGA_BYTE (targa_header.image_type);
904 
905 	GET_TGA_BYTE (tmp[0]);
906 	GET_TGA_BYTE (tmp[1]);
907 	targa_header.colormap_index = LittleShort ( *((short *)tmp) );
908 	GET_TGA_BYTE (tmp[0]);
909 	GET_TGA_BYTE (tmp[1]);
910 	targa_header.colormap_length = LittleShort ( *((short *)tmp) );
911 	GET_TGA_BYTE (targa_header.colormap_size);
912 	GET_TGA_BYTE (tmp[0]);
913 	GET_TGA_BYTE (tmp[1]);
914 	targa_header.x_origin = LittleShort ( *((short *)tmp) );
915 	GET_TGA_BYTE (tmp[0]);
916 	GET_TGA_BYTE (tmp[1]);
917 	targa_header.y_origin = LittleShort ( *((short *)tmp) );
918 	GET_TGA_BYTE (tmp[0]);
919 	GET_TGA_BYTE (tmp[1]);
920 	targa_header.width = LittleShort ( *((short *)tmp) );
921 	GET_TGA_BYTE (tmp[0]);
922 	GET_TGA_BYTE (tmp[1]);
923 	targa_header.height = LittleShort ( *((short *)tmp) );
924 	GET_TGA_BYTE (targa_header.pixel_size);
925 	GET_TGA_BYTE (targa_header.attributes);
926 
927 	if (targa_header.image_type!=2
928 		&& targa_header.image_type!=10) {
929 		//Com_Error (ERR_DROP, "LoadTGA: Only type 2 and 10 targa RGB images supported\n");
930 		if (buffer != static_rawdata)
931 			FS_FreeFile (buffer);
932 		return;
933 	}
934 
935 	if (targa_header.colormap_type !=0
936 		|| (targa_header.pixel_size!=32 && targa_header.pixel_size!=24)) {
937 		//Com_Error (ERR_DROP, "LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
938 		if (buffer != static_rawdata)
939 			FS_FreeFile (buffer);
940 		return;
941 	}
942 
943 	columns = targa_header.width;
944 	rows = targa_header.height;
945 	numPixels = columns * rows;
946 
947 	if (width)
948 		*width = columns;
949 	if (height)
950 		*height = rows;
951 
952 	targa_rgba = malloc (numPixels*4);
953 	memset (targa_rgba, 0, numPixels*4);
954 	*pic = targa_rgba;
955 
956 	if (targa_header.id_length != 0)
957 		buf_p += targa_header.id_length;  // skip TARGA image comment
958 
959 	if (targa_header.image_type==2) {  // Uncompressed, RGB images
960 		for(row=rows-1; row>=0; row--) {
961 			pixbuf = targa_rgba + row*columns*4;
962 			for(column=0; column<columns; column++) {
963 				unsigned char red,green,blue,alphabyte=255;
964 				GET_TGA_BYTE (blue);
965 				GET_TGA_BYTE (green);
966 				GET_TGA_BYTE (red);
967 				if (targa_header.pixel_size == 32)
968 				{
969 					GET_TGA_BYTE (alphabyte);
970 				}
971 				*pixbuf++ = red;
972 				*pixbuf++ = green;
973 				*pixbuf++ = blue;
974 				*pixbuf++ = alphabyte;
975 			}
976 		}
977 	}
978 	else if (targa_header.image_type==10) {   // Runlength encoded RGB images
979 		unsigned char red=0,green=0,blue=0,alphabyte=255,packetHeader,packetSize,j;
980 		for(row=rows-1; row>=0; row--) {
981 			pixbuf = targa_rgba + row*columns*4;
982 			for(column=0; column<columns; ) {
983 				GET_TGA_BYTE (packetHeader);
984 				packetSize = 1 + (packetHeader & 0x7f);
985 				if (packetHeader & 0x80) {        // run-length packet
986 					GET_TGA_BYTE (blue);
987 					GET_TGA_BYTE (green);
988 					GET_TGA_BYTE (red);
989 					if (targa_header.pixel_size == 32)
990 						GET_TGA_BYTE (alphabyte);
991 
992 					for(j=0;j<packetSize;j++) {
993 						*pixbuf++ = red;
994 						*pixbuf++ = green;
995 						*pixbuf++ = blue;
996 						*pixbuf++ = alphabyte;
997 						column++;
998 						if (column==columns) { // run spans across rows
999 							column=0;
1000 							if (row>0)
1001 								row--;
1002 							else
1003 								goto breakOut;
1004 							pixbuf = targa_rgba + row*columns*4;
1005 						}
1006 					}
1007 				}
1008 				else {                            // non run-length packet
1009 					for(j=0;j<packetSize;j++) {
1010 						GET_TGA_BYTE (blue);
1011 						GET_TGA_BYTE (green);
1012 						GET_TGA_BYTE (red);
1013 						if (targa_header.pixel_size == 32)
1014 							GET_TGA_BYTE (alphabyte);
1015 						*pixbuf++ = red;
1016 						*pixbuf++ = green;
1017 						*pixbuf++ = blue;
1018 						*pixbuf++ = alphabyte;
1019 						column++;
1020 						if (column==columns) { // pixel packet run spans across rows
1021 							column=0;
1022 							if (row>0)
1023 								row--;
1024 							else
1025 								goto breakOut;
1026 							pixbuf = targa_rgba + row*columns*4;
1027 						}
1028 					}
1029 				}
1030 			}
1031 			breakOut:;
1032 		}
1033 	}
1034 
1035 	if (buffer != static_rawdata)
1036 		FS_FreeFile (buffer);
1037 }
1038 
1039 
1040 /*
1041 ====================================================================
1042 
1043 IMAGE FLOOD FILLING
1044 
1045 ====================================================================
1046 */
1047 
1048 
1049 /*
1050 =================
1051 Mod_FloodFillSkin
1052 
1053 Fill background pixels so mipmapping doesn't have haloes
1054 =================
1055 */
1056 
1057 typedef struct
1058 {
1059 	short		x, y;
1060 } floodfill_t;
1061 
1062 // must be a power of 2
1063 #define FLOODFILL_FIFO_SIZE 0x1000
1064 #define FLOODFILL_FIFO_MASK (FLOODFILL_FIFO_SIZE - 1)
1065 
1066 #define FLOODFILL_STEP( off, dx, dy ) \
1067 { \
1068 	if (pos[off] == fillcolor) \
1069 	{ \
1070 		pos[off] = 255; \
1071 		fifo[inpt].x = x + (dx), fifo[inpt].y = y + (dy); \
1072 		inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; \
1073 	} \
1074 	else if (pos[off] != 255) fdc = pos[off]; \
1075 }
1076 
R_FloodFillSkin(byte * skin,int skinwidth,int skinheight)1077 void R_FloodFillSkin( byte *skin, int skinwidth, int skinheight )
1078 {
1079 	byte				fillcolor = *skin; // assume this is the pixel to fill
1080 	floodfill_t			fifo[FLOODFILL_FIFO_SIZE];
1081 	int					inpt = 0, outpt = 0;
1082 	int					filledcolor = -1;
1083 	int					i;
1084 
1085 	if (filledcolor == -1)
1086 	{
1087 		filledcolor = 0;
1088 		// attempt to find opaque black
1089 		for (i = 0; i < 256; ++i)
1090 			if (d_8to24table[i] == (255 << 0)) // alpha 1.0
1091 			{
1092 				filledcolor = i;
1093 				break;
1094 			}
1095 	}
1096 
1097 	// can't fill to filled color or to transparent color (used as visited marker)
1098 	if ((fillcolor == filledcolor) || (fillcolor == 255))
1099 	{
1100 		//printf( "not filling skin from %d to %d\n", fillcolor, filledcolor );
1101 		return;
1102 	}
1103 
1104 	fifo[inpt].x = 0, fifo[inpt].y = 0;
1105 	inpt = (inpt + 1) & FLOODFILL_FIFO_MASK;
1106 
1107 	while (outpt != inpt)
1108 	{
1109 		int			x = fifo[outpt].x, y = fifo[outpt].y;
1110 		int			fdc = filledcolor;
1111 		byte		*pos = &skin[x + skinwidth * y];
1112 
1113 		outpt = (outpt + 1) & FLOODFILL_FIFO_MASK;
1114 
1115 		if (x > 0)				FLOODFILL_STEP( -1, -1, 0 );
1116 		if (x < skinwidth - 1)	FLOODFILL_STEP( 1, 1, 0 );
1117 		if (y > 0)				FLOODFILL_STEP( -skinwidth, 0, -1 );
1118 		if (y < skinheight - 1)	FLOODFILL_STEP( skinwidth, 0, 1 );
1119 		skin[x + skinwidth * y] = fdc;
1120 	}
1121 }
1122 
1123 //=======================================================
1124 
1125 
1126 /*
1127 ================
1128 GL_ResampleTexture
1129 ================
1130 */
GL_ResampleTexture(byte * in,int inwidth,int inheight,byte * out,int outwidth,int outheight)1131 void GL_ResampleTexture (byte *in, int inwidth, int inheight, byte *out, int outwidth, int outheight)
1132 {
1133 	int		i, j;
1134 	byte	*inrow, *inrow2;
1135 	unsigned	frac, fracstep;
1136 	unsigned	p1[1024], p2[1024];
1137 	byte		*pix1, *pix2, *pix3, *pix4;
1138 
1139 	fracstep = inwidth*0x10000/outwidth;
1140 
1141 	frac = fracstep>>2;
1142 	for (i=0 ; i<outwidth ; i++)
1143 	{
1144 		p1[i] = 4*(frac>>16);
1145 		frac += fracstep;
1146 	}
1147 	frac = 3*(fracstep>>2);
1148 	for (i=0 ; i<outwidth ; i++)
1149 	{
1150 		p2[i] = 4*(frac>>16);
1151 		frac += fracstep;
1152 	}
1153 
1154 	for (i=0 ; i<outheight ; i++, out += outwidth*4)
1155 	{
1156 		inrow = in + 4*inwidth*(int)((i+0.25)*inheight/outheight);
1157 		inrow2 = in + 4*inwidth*(int)((i+0.75)*inheight/outheight);
1158 		frac = fracstep >> 1;
1159 		for (j=0 ; j<outwidth ; j++)
1160 		{
1161 			pix1 = inrow + p1[j];
1162 			pix2 = inrow + p2[j];
1163 			pix3 = inrow2 + p1[j];
1164 			pix4 = inrow2 + p2[j];
1165 			*(out+4*j+0) = (pix1[0] + pix2[0] + pix3[0] + pix4[0])>>2;
1166 			*(out+4*j+1) = (pix1[1] + pix2[1] + pix3[1] + pix4[1])>>2;
1167 			*(out+4*j+2) = (pix1[2] + pix2[2] + pix3[2] + pix4[2])>>2;
1168 			*(out+4*j+3) = (pix1[3] + pix2[3] + pix3[3] + pix4[3])>>2;
1169 		}
1170 	}
1171 }
1172 
1173 /*
1174 R_FilterTexture
1175 
1176 Applies brightness and contrast to the specified image while optionally computing
1177 the image's average color.  Also handles image inversion and monochrome.  This is
1178 all munged into one function to reduce loops on level load.
1179 */
R_FilterTexture(byte * in,int width,int height)1180 void R_FilterTexture(byte *in, int width, int height)
1181 {
1182 	int count;
1183 	float fcb;
1184 	int ix;
1185 	static byte lut[256];
1186 	static int first_time = 1;
1187 	static float lut_gamma = 0.0f;
1188 	static float lut_contrast = 0.0f;
1189 
1190 	if ( lut_gamma != vid_gamma->value || lut_contrast != vid_contrast->value || first_time ) {
1191 		first_time = 0;
1192 		lut_gamma = vid_gamma->value;
1193 		lut_contrast = vid_contrast->value;
1194 		// build lookup table
1195 		for ( ix = 0; ix < sizeof(lut); ix++ ) {
1196 			fcb = (float)ix / 255.0f;
1197 			fcb *= lut_gamma;
1198 			if (fcb < 0.0f )
1199 				fcb = 0.0f;
1200 			fcb -= 0.5f;
1201 			fcb *= lut_contrast;
1202 			fcb += 0.5f;
1203 			fcb *= 255.0f;
1204 			if ( fcb >= 255.0f )
1205 				lut[ix] = 255 ;
1206 			else if (fcb <= 0.0f )
1207 				lut[ix] = 0;
1208 			else
1209 				lut[ix] = (byte)fcb;
1210 		}
1211 	}
1212 
1213 	// apply to image
1214 	count = width * height;
1215 	while ( count-- ) {
1216 		*in = lut[*in];
1217 		++in;
1218 		*in = lut[*in];
1219 		++in;
1220 		*in = lut[*in];
1221 		++in;
1222 		++in;
1223 	}
1224 
1225 }
1226 
1227 
1228 #define ALPHATEST_THRESHOLD 169
1229 // Uses the canonical mipmap generation algorithm, but unlike OpenGL's built-
1230 // in mipmapping, it this function knows when to quit-- that is, when the
1231 // mipmaps have gotten too "mushy." Mushy mipmaps usually aren't a problem,
1232 // but they're a huge one when dealing with alphatest surfaces.
GL_RecursiveGenerateAlphaMipmaps(byte * data,int width,int height,int depth)1233 int GL_RecursiveGenerateAlphaMipmaps (byte *data, int width, int height, int depth)
1234 {
1235 	int			ret;
1236 	int			x, y;
1237 	int			newwidth, newheight;
1238 	int			upper_left_alpha;
1239 	qboolean	uniform = true;
1240 	byte		*mipmap, *scan, *scan2, *out;
1241 
1242 	if (width == 1 && height == 1)
1243 		return depth;
1244 
1245 	newwidth = width;
1246 	if (newwidth > 1)
1247 		newwidth /= 2;
1248 	newheight = height;
1249 	if (newheight > 1)
1250 		newheight /= 2;
1251 
1252 	mipmap = malloc (newwidth*newheight*4);
1253 
1254 	for (y = 0; (y+1) < height; y += 2)
1255 	{
1256 		for (x = 0; (x+1) < width; x += 2)
1257 		{
1258 			scan = data + (y*width+x)*4;
1259 			scan2 = data + ((y+1)*width+x)*4;
1260 			out = mipmap + ((y/2)*(width/2)+(x/2))*4;
1261 			out[0] = (scan[0]+scan[4]+scan2[0]+scan2[4])/4;
1262 			out[1] = (scan[1]+scan[5]+scan2[1]+scan2[5])/4;
1263 			out[2] = (scan[2]+scan[6]+scan2[2]+scan2[6])/4;
1264 			out[3] = (scan[3]+scan[7]+scan2[3]+scan2[7])/4;
1265 			if (x == 0 && y == 0)
1266 				upper_left_alpha = out[3];
1267 			else if ((upper_left_alpha > ALPHATEST_THRESHOLD) != (out[3] > ALPHATEST_THRESHOLD))
1268 				uniform = false;
1269 		}
1270 	}
1271 
1272 	if (uniform)
1273 	{
1274 		free (mipmap);
1275 		return depth;
1276 	}
1277 
1278 	ret = GL_RecursiveGenerateAlphaMipmaps (mipmap, newwidth, newheight, depth+1);
1279 
1280 	qglTexImage2D (GL_TEXTURE_2D, depth+1, gl_tex_alpha_format, newwidth, newheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, mipmap);
1281 
1282 	free (mipmap);
1283 	return ret;
1284 }
1285 
GL_GenerateAlphaMipmaps(byte * data,int width,int height)1286 int GL_GenerateAlphaMipmaps (byte *data, int width, int height)
1287 {
1288 	return GL_RecursiveGenerateAlphaMipmaps (data, width, height, 0);
1289 }
1290 
1291 
1292 static int	powers_of_two[] = {16,32,64,128,256,512,1024,2048,4096};
1293 int		upload_width, upload_height;
1294 int		crop_left, crop_right, crop_top, crop_bottom;
1295 qboolean	uploaded_paletted;
1296 
1297 
GL_Upload32(byte * data,int width,int height,int picmip,qboolean filter,qboolean force_standard_mipmap)1298 qboolean GL_Upload32 (byte *data, int width, int height, int picmip, qboolean filter, qboolean force_standard_mipmap)
1299 {
1300 	int		samples;
1301 	byte 	*scaled;
1302 	int		scaled_width, scaled_height;
1303 	int		i, c;
1304 	byte		*scan;
1305 	int comp;
1306 
1307 	if(filter)
1308 		R_FilterTexture(data, width, height);
1309 
1310 	uploaded_paletted = false;    // scan the texture for any non-255 alpha
1311 	c = width*height;
1312 	scan = data + 3;
1313 	samples = gl_solid_format;
1314 	for (i=0 ; i<c ; i++, scan += 4)
1315 	{
1316 		if ( *scan != 255 )
1317 		{
1318 			samples = gl_alpha_format;
1319 			break;
1320 		}
1321 	}
1322 	comp = (samples == gl_solid_format) ? gl_tex_solid_format : gl_tex_alpha_format;
1323 
1324 	{
1325 		int max_size;
1326 		int i;
1327 		qglGetIntegerv(GL_MAX_TEXTURE_SIZE,&max_size);
1328 		scaled_width = scaled_height = 0;
1329 
1330 		for (i=0; i<8; i++)
1331 		{
1332 			if (width >= powers_of_two[i] && width < powers_of_two[i+1]) {
1333 				if (width > ((powers_of_two[i] + powers_of_two[i+1])/2))
1334 					scaled_width = powers_of_two[i+1];
1335 				else
1336 					scaled_width = powers_of_two[i];
1337 			} else if (width == powers_of_two[i+1]) {
1338 				scaled_width = powers_of_two[i+1];
1339 			}
1340 
1341 			if (scaled_width && scaled_height)
1342 				break;
1343 			if (height >= powers_of_two[i] && height < powers_of_two[i+1]) {
1344 				if (height > ((powers_of_two[i] + powers_of_two[i+1])/2))
1345 					scaled_height = powers_of_two[i+1];
1346 				else
1347 					scaled_height = powers_of_two[i];
1348 			} else if (height == powers_of_two[i+1]) {
1349 				scaled_height = powers_of_two[i+1];
1350 			}
1351 			if (scaled_width && scaled_height)
1352 				break;
1353 		}
1354 		// let people sample down the world textures for speed
1355 		for (i = 0; i < picmip; i++)
1356 		{
1357 			if (scaled_width <= 1 || scaled_height <= 1)
1358 				break;
1359 			scaled_width >>= 1;
1360 			scaled_height >>= 1;
1361 		}
1362 		if (scaled_width > max_size)
1363 			scaled_width = max_size;
1364 		if (scaled_height > max_size)
1365 			scaled_height = max_size;
1366 	}
1367 
1368 	if (scaled_width != width || scaled_height != height) {
1369 		scaled=malloc((scaled_width * scaled_height) * 4);
1370 		GL_ResampleTexture(data,width,height,scaled,scaled_width,scaled_height);
1371 	} else {
1372 		scaled=data;
1373 	}
1374 
1375 	if (samples != gl_alpha_format || force_standard_mipmap)
1376 		qglTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE );
1377 	qglTexImage2D (GL_TEXTURE_2D, 0, comp, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
1378 
1379 	crop_left = crop_right = crop_top = crop_bottom = 0;
1380 	if (samples == gl_alpha_format)
1381 	{
1382 		int			x, y;
1383 		qboolean 	found;
1384 
1385 		scan = (byte*)scaled+3;
1386 
1387 		for (y = 0; y < scaled_height; y++, crop_top++)
1388 		{
1389 			found = false;
1390 			for (x = 0; x < scaled_width; x++)
1391 			{
1392 				scan = ((byte*)scaled + (y*scaled_width+x)*4+3);
1393 				if (*scan != 0)
1394 					found = true;
1395 			}
1396 			if (found)
1397 				break;
1398 		}
1399 
1400 		crop_left = scaled_width;
1401 		crop_right = scaled_width;
1402 
1403 		for (; y < scaled_height; y++)
1404 		{
1405 			for (x = 0; x < scaled_width; x++)
1406 			{
1407 				scan = ((byte*)scaled + (y*scaled_width+x)*4+3);
1408 				if (*scan != 0)
1409 				{
1410 					if (x < crop_left)
1411 						crop_left = x;
1412 					if (scaled_width-x-1 < crop_right)
1413 						crop_right = scaled_width-x-1;
1414 					crop_bottom = scaled_height-y-1;
1415 				}
1416 			}
1417 		}
1418 	}
1419 
1420 	if (samples == gl_alpha_format && !force_standard_mipmap)
1421 	{
1422 		int generated_mipmaps =
1423 			GL_GenerateAlphaMipmaps (scaled, scaled_width, scaled_height);
1424 		qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, generated_mipmaps);
1425 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, r_alphamasked_anisotropic->integer);
1426 	}
1427 	else
1428 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, r_anisotropic->integer);
1429 
1430 	if (scaled_width != width || scaled_height != height)
1431 		free(scaled);
1432 
1433 	upload_width = scaled_width;
1434 	upload_height = scaled_height;
1435 	qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
1436 	qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
1437 
1438 	return (samples == gl_alpha_format);
1439 }
1440 
1441 /*
1442 ===============
1443 GL_Upload8
1444 
1445 Returns has_alpha
1446 ===============
1447 */
GL_Upload8(byte * data,int width,int height,int picmip,qboolean filter)1448 qboolean GL_Upload8 (byte *data, int width, int height, int picmip, qboolean filter)
1449 {
1450 	unsigned	trans[512*256]; // contains 32 bit RGBA color
1451 	int			i, s;
1452 	int			p;
1453 
1454 	s = width*height;
1455 
1456 	if (s > sizeof(trans)/4)
1457 		Com_Error (ERR_DROP, "GL_Upload8: too large");
1458 
1459 	for (i=0 ; i<s ; i++)
1460     {
1461 		p = data[i];
1462         trans[i] = d_8to24table[p];
1463 
1464         if (p == 255)
1465         {   // transparent, so scan around for another color
1466             // to avoid alpha fringes
1467             // FIXME: do a full flood fill so mips work...
1468             if (i > width && data[i-width] != 255)
1469                 p = data[i-width];
1470             else if (i < s-width && data[i+width] != 255)
1471                 p = data[i+width];
1472             else if (i > 0 && data[i-1] != 255)
1473                 p = data[i-1];
1474             else if (i < s-1 && data[i+1] != 255)
1475                 p = data[i+1];
1476             else
1477                 p = 0;
1478             // copy rgb components
1479             ((byte *)&trans[i])[0] = ((byte *)&d_8to24table[p])[0];
1480             ((byte *)&trans[i])[1] = ((byte *)&d_8to24table[p])[1];
1481             ((byte *)&trans[i])[2] = ((byte *)&d_8to24table[p])[2];
1482         }
1483     }
1484     return GL_Upload32 ((byte*)trans, width, height, picmip, filter, false);
1485 }
1486 
1487 /*
1488 ================
1489 GL_ReservePic
1490 
1491 Find a free image_t
1492 ================
1493 */
GL_FindFreeImage(char * name,int width,int height,imagetype_t type)1494 image_t *GL_FindFreeImage (char *name, int width, int height, imagetype_t type)
1495 {
1496 	image_t		*image;
1497 	int			i;
1498 
1499 	// find a free image_t
1500 	for (i=0, image=gltextures ; i<numgltextures ; i++,image++)
1501 	{
1502 		if (!image->texnum)
1503 			break;
1504 	}
1505 	if (i == numgltextures)
1506 	{
1507 		if (numgltextures == MAX_GLTEXTURES)
1508 			Com_Error (ERR_DROP, "MAX_GLTEXTURES");
1509 		numgltextures++;
1510 	}
1511 	image = &gltextures[i];
1512 
1513 	if (strlen(name) >= sizeof(image->name))
1514 		Com_Error (ERR_DROP, "Draw_LoadPic: \"%s\" is too long", name);
1515 
1516 	strcpy (image->name, name);
1517 
1518 	if ( name[0] != '*' )
1519 	{ // not a special name, remove the path part
1520 		strcpy( image->bare_name, COM_SkipPath( name ) );
1521 	}
1522 
1523 	image->registration_sequence = registration_sequence;
1524 
1525 	image->width = width;
1526 	image->height = height;
1527 	image->type = type;
1528 
1529 	image->texnum = TEXNUM_IMAGES + (image - gltextures);
1530 
1531 	return image;
1532 }
1533 
1534 /*
1535 ================
1536 GL_LoadPic
1537 
1538 This is also used as an entry point for the generated r_notexture
1539 ================
1540 */
GL_LoadPic(char * name,byte * pic,int width,int height,imagetype_t type,int bits)1541 image_t *GL_LoadPic (char *name, byte *pic, int width, int height, imagetype_t type, int bits)
1542 {
1543 	image_t		*image;
1544 	int			i;
1545 	int			picmip;
1546 
1547 	image = GL_FindFreeImage (name, width, height, type);
1548 
1549 	if (type == it_skin && bits == 8)
1550 		R_FloodFillSkin(pic, width, height);
1551 
1552 	if (type == it_particle || type == it_pic)
1553 		picmip = 0;
1554 	else
1555 		picmip = gl_picmip->integer;
1556 
1557 	// load little particles into the scrap
1558 	if (type == it_particle && bits != 8
1559 		&& image->width <= 128 && image->height <= 128)
1560 	{
1561 		int		x, y;
1562 		int		i, j, k, l;
1563 		int		texnum;
1564 
1565 		texnum = Scrap_AllocBlock (image->width, image->height, &x, &y);
1566 		if (texnum == -1)
1567 			goto nonscrap;
1568 		scrap_dirty = true;
1569 
1570 		// copy the texels into the scrap block
1571 		k = 0;
1572 		for (i=0 ; i<image->height ; i++)
1573 			for (j=0 ; j<image->width ; j++)
1574 			    for (l = 0; l < 4; l++, k++)
1575 				    scrap_texels[texnum][((y+i)*BLOCK_WIDTH + x + j)*4+l] = pic[k];
1576 		image->texnum = TEXNUM_SCRAPS + texnum; // overwrite old texnum
1577 		image->scrap = true;
1578 		image->has_alpha = true;
1579 		image->sl = (double)(x+0.5)/(double)BLOCK_WIDTH;
1580 		image->sh = (double)(x+image->width-0.5)/(double)BLOCK_WIDTH;
1581 		image->tl = (double)(y+0.5)/(double)BLOCK_HEIGHT;
1582 		image->th = (double)(y+image->height-0.5)/(double)BLOCK_HEIGHT;
1583 	}
1584 	else
1585 	{
1586 nonscrap:
1587 		image->scrap = false;
1588 		GL_Bind(image->texnum);
1589 		if (bits == 8) {
1590 			image->has_alpha = GL_Upload8 (pic, width, height, picmip, type <= it_wall);
1591 		} else {
1592 			image->has_alpha = GL_Upload32 (pic, width, height, picmip, type <= it_wall, type >= it_bump);
1593 		}
1594 
1595 		if (type == it_pic)
1596 			qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
1597 
1598 		image->paletted = uploaded_paletted;
1599 
1600 		// size in pixels after power of 2 and scales
1601 		image->upload_width = upload_width;
1602 		image->upload_height = upload_height;
1603 
1604 		// vertex offset to apply when cropping
1605 		image->crop_left = crop_left;
1606 		image->crop_top = crop_top;
1607 
1608 		// size in pixels after cropping
1609 		image->crop_width = upload_width-crop_left-crop_right;
1610 		image->crop_height = upload_height-crop_top-crop_bottom;
1611 
1612 		// texcoords to use when not cropping
1613 		image->sl = 0;
1614 		image->sh = 1;
1615 		image->tl = 0;
1616 		image->th = 1;
1617 
1618 		// texcoords to use when cropping
1619 		image->crop_sl = 0 + (float)crop_left/(float)upload_width;
1620 		image->crop_sh = 1 - (float)crop_right/(float)upload_width;
1621 		image->crop_tl = 0 + (float)crop_top/(float)upload_height;
1622 		image->crop_th = 1 - (float)crop_bottom/(float)upload_height;
1623 	}
1624 
1625 	COMPUTE_HASH_KEY( image->hash_key, name, i );
1626 	return image;
1627 }
1628 
1629 
1630 /*
1631 ================
1632 GL_LoadWal
1633 ================
1634 */
GL_LoadWal(char * name)1635 image_t *GL_LoadWal (char *name)
1636 {
1637 	miptex_t	*mt;
1638 	int			width, height, ofs;
1639 	image_t		*image;
1640 
1641 	FS_LoadFile (name, (void **)&mt);
1642 	if (!mt)
1643 	{
1644 		return r_notexture;
1645 	}
1646 
1647 	width = LittleLong (mt->width);
1648 	height = LittleLong (mt->height);
1649 	ofs = LittleLong (mt->offsets[0]);
1650 
1651 	image = GL_LoadPic (name, (byte *)mt + ofs, width, height, it_wall, 8);
1652 
1653 	FS_FreeFile ((void *)mt);
1654 
1655 	return image;
1656 }
1657 
1658 
1659 /*
1660 ===============
1661 GL_GetImage
1662 
1663 Finds an image, do not attempt to load it
1664 ===============
1665 */
GL_GetImage(const char * name)1666 image_t *GL_GetImage( const char * name )
1667 {
1668 	image_t *	image = NULL;
1669 	unsigned int	hash_key;
1670 	int		i;
1671 
1672 	COMPUTE_HASH_KEY( hash_key, name, i );
1673 	for ( i = 0, image=gltextures ; i<numgltextures ; i++,image++)
1674 	{
1675 		if (hash_key == image->hash_key && !strcmp(name, image->name))
1676 		{
1677 			image->registration_sequence = registration_sequence;
1678 			return image;
1679 		}
1680 	}
1681 
1682 	return NULL;
1683 }
1684 
1685 
1686 /*
1687 ===============
1688 GL_FreeImage
1689 
1690 Frees an image slot and deletes the texture
1691 ===============
1692 */
GL_FreeImage(image_t * image)1693 void GL_FreeImage( image_t * image )
1694 {
1695 	if ( ! image->texnum )
1696 		return;
1697 	qglDeleteTextures (1, (unsigned *)&image->texnum );
1698 	if ( gl_state.currenttextures[gl_state.currenttmu] == image->texnum ) {
1699 		gl_state.currenttextures[ gl_state.currenttmu ] = 0;
1700 	}
1701 	memset (image, 0, sizeof(*image));
1702 }
1703 
1704 
1705 /*
1706 ===============
1707 GL_FindImage
1708 
1709 Finds or loads the given image
1710 ===============
1711 */
GL_FindImage(char * name,imagetype_t type)1712 image_t	*GL_FindImage (char *name, imagetype_t type)
1713 {
1714 	image_t		*image = NULL;
1715 	int		len;
1716 	byte		*pic, *palette;
1717 	int		width, height;
1718 	char		shortname[MAX_QPATH];
1719 
1720 	if (!name)
1721 		goto ret_image;	//	Com_Error (ERR_DROP, "GL_FindImage: NULL name");
1722 	len = strlen(name);
1723 	if (len < 5)
1724 		goto ret_image;	//	Com_Error (ERR_DROP, "GL_FindImage: bad name: %s", name);
1725 
1726 	//if HUD, then we want to load the one according to what it is set to.
1727 	if(!strcmp(name, "pics/i_health.pcx"))
1728 			strcpy(name, cl_hudimage1->string);
1729 	if(!strcmp(name, "pics/i_score.pcx"))
1730 			strcpy(name, cl_hudimage2->string);
1731 
1732 	// look for it
1733 	image = GL_GetImage( name );
1734 	if ( image != NULL )
1735 		return image;
1736 
1737 	// strip off .pcx, .tga, etc...
1738 	COM_StripExtension ( name, shortname );
1739 
1740 	//
1741 	// load the pic from disk
1742 	//
1743 	pic = NULL;
1744 	palette = NULL;
1745 
1746 	// Try to load the image with different file extensions, in the following
1747 	// order of decreasing preference: TGA, JPEG, PCX, and WAL.
1748 
1749 	LoadTGA (va("%s.tga", shortname), &pic, &width, &height);
1750 	if (pic)
1751 	{
1752 		image = GL_LoadPic (name, pic, width, height, type, 32);
1753 		goto done;
1754 	}
1755 
1756 	LoadJPG (va("%s.jpg", shortname), &pic, &width, &height);
1757 	if (pic)
1758 	{
1759 		image = GL_LoadPic (name, pic, width, height, type, 32);
1760 		goto done;
1761 	}
1762 
1763 	// TGA and JPEG are the only file types used for heightmaps and
1764 	// normalmaps, so if we haven't found it yet, it isn't there, and we can
1765 	// save ourselves a file lookup.
1766 	if (type == it_bump)
1767 		goto done;
1768 
1769 	LoadPCX (va("%s.pcx", shortname), &pic, &palette, &width, &height);
1770 	if (pic)
1771 	{
1772 		image = GL_LoadPic (name, pic, width, height, type, 8);
1773 		goto done;
1774 	}
1775 
1776 	if (type == it_wall)
1777 		image = GL_LoadWal (va("%s.wal", shortname));
1778 
1779 done:
1780 	if (pic)
1781 		free(pic);
1782 	if (palette)
1783 		free(palette);
1784 
1785 	if (image != NULL)
1786 		image->script = RS_FindScript (shortname);
1787 
1788 ret_image:
1789 	return image;
1790 }
1791 
1792 
1793 
1794 /*
1795 ===============
1796 R_RegisterSkin
1797 ===============
1798 */
R_RegisterSkin(char * name)1799 struct image_s *R_RegisterSkin (char *name)
1800 {
1801 	return GL_FindImage (name, it_skin);
1802 }
1803 
1804 
1805 /*
1806 ================
1807 GL_FreeUnusedImages
1808 
1809 Any image that was not touched on this registration sequence
1810 will be freed.
1811 ================
1812 */
GL_FreeUnusedImages(void)1813 void GL_FreeUnusedImages (void)
1814 {
1815 	int		i;
1816 	image_t	*image;
1817 
1818 	// never free r_notexture
1819 	r_notexture->registration_sequence = registration_sequence;
1820 
1821 	for (i=0, image=gltextures ; i<numgltextures ; i++, image++)
1822 	{
1823 		if (image->registration_sequence == registration_sequence)
1824 			continue;		// used this sequence
1825 		if (!image->registration_sequence)
1826 			continue;		// free image_t slot
1827 		if (image->type == it_pic || image->type == it_sprite || image->type == it_particle)
1828 			continue;		// don't free pics or particles
1829 		// free it
1830 		qglDeleteTextures (1, (unsigned *)&image->texnum );
1831 		memset (image, 0, sizeof(*image));
1832 	}
1833 }
1834 
1835 /*
1836 ===============
1837 Draw_GetPalette
1838 ===============
1839 */
Draw_GetPalette(void)1840 int Draw_GetPalette (void)
1841 {
1842 	int		i;
1843 	int		r, g, b;
1844 	unsigned	v;
1845 	byte	*pic, *pal;
1846 	int		width, height;
1847 
1848 	// get the palette
1849 
1850 	LoadPCX ("pics/colormap.pcx", &pic, &pal, &width, &height);
1851 	if (!pal)
1852 	{
1853 		Com_Error (ERR_FATAL,
1854 				"Couldn't load pics/colormap.pcx\n"
1855 				"The game executable cannot find its data files. This means\n"
1856 				"the game is likely not installed correctly."
1857 				// TODO: automatically generate a list of paths where the data
1858 				// files should be
1859 #if defined UNIX_VARIANT
1860 				" If you\ninstalled the game from the repository of a Linux\n"
1861 				"distribution, please report this to ther package\n"
1862 				"maintainers and have them check the README for packaging\n"
1863 				"instructions."
1864 #endif //UNIX_VARIANT
1865 			);
1866 	}
1867 
1868 	for (i=0 ; i<256 ; i++)
1869 	{
1870 		r = pal[i*3+0];
1871 		g = pal[i*3+1];
1872 		b = pal[i*3+2];
1873 
1874 		v = (255<<24) + (r<<0) + (g<<8) + (b<<16);
1875 		d_8to24table[i] = LittleLong(v);
1876 	}
1877 
1878 	d_8to24table[255] &= LittleLong(0xffffff);	// 255 is transparent
1879 
1880 	free (pic);
1881 	free (pal);
1882 
1883 	return 0;
1884 }
1885 
1886 // TODO: have r_newrefdef available before calling these, put r_mirroretxture
1887 // in that struct, base it on the viewport specified in that struct. (Needed
1888 // for splitscreen.)
R_InitMirrorTextures(void)1889 void R_InitMirrorTextures( void )
1890 {
1891 	byte	*data;
1892 	int		size;
1893 	int		size_oneside;
1894 
1895 	//init the partial screen texture
1896 	size_oneside = ceil((512.0f/1080.0f)*(float)viddef.height);
1897 	size = size_oneside * size_oneside * 4;
1898 	data = malloc( size );
1899 	memset( data, 255, size );
1900 	r_mirrortexture = GL_LoadPic( "***r_mirrortexture***", (byte *)data, size_oneside, size_oneside, it_pic, 32 );
1901 	free ( data );
1902 }
1903 
R_InitDepthTextures(void)1904 void R_InitDepthTextures( void )
1905 {
1906 	byte	*data;
1907 	int		size, texture_height, texture_width;
1908 
1909 	//find closer power of 2 to screen size
1910 	for (texture_width = 1;texture_width < viddef.width;texture_width *= 2);
1911 	for (texture_height = 1;texture_height < viddef.height;texture_height *= 2);
1912 
1913 	//limit to 2048x2048 - anything larger is generally going to cause problems, and AA doesn't support res higher
1914 	if(texture_width > 2048)
1915 		texture_width = 2048;
1916 	if(texture_height > 2048)
1917 		texture_height = 2048;
1918 
1919 	//init the framebuffer textures
1920 	size = texture_width * texture_height * 4;
1921 
1922 	data = malloc( size );
1923 	memset( data, 255, size );
1924 	r_depthtexture = GL_LoadPic( "***r_depthtexture***", (byte *)data, texture_width, texture_height, it_pic, 3 );
1925 	r_depthtexture2 = GL_LoadPic( "***r_depthtexture2***", (byte *)data, texture_width, texture_height, it_pic, 3 );
1926 	free ( data );
1927 }
1928 
1929 
1930 /*
1931 ===============
1932 GL_InitImages
1933 ===============
1934 */
GL_InitImages(void)1935 void	GL_InitImages (void)
1936 {
1937 
1938 	registration_sequence = 1;
1939 
1940 	gl_state.inverse_intensity = 1;
1941 
1942 	Draw_GetPalette ();
1943 
1944 	R_InitMirrorTextures();//MIRRORS
1945 	R_InitDepthTextures();//DEPTH(SHADOWMAPS)
1946 	R_FB_InitTextures();//FULLSCREEN EFFECTS
1947 	R_SI_InitTextures();//SIMPLE ITEMS
1948 	R_InitBloomTextures();//BLOOMS
1949 }
1950 
1951 /*
1952 ===============
1953 GL_ShutdownImages
1954 ===============
1955 */
GL_ShutdownImages(void)1956 void	GL_ShutdownImages (void)
1957 {
1958 	int		i;
1959 	image_t	*image;
1960 
1961 	for (i=0, image=gltextures ; i<numgltextures ; i++, image++)
1962 	{
1963 		if (!image->registration_sequence)
1964 			continue;		// free image_t slot
1965 		// free it
1966 		qglDeleteTextures (1, (unsigned *)&image->texnum);
1967 		memset (image, 0, sizeof(*image));
1968 	}
1969 
1970 	memset (scrap_allocated, 0, sizeof(scrap_allocated));
1971 	memset (scrap_texels, 0, sizeof(scrap_texels));
1972 	scrap_dirty = false;
1973 	scrap_uploads = 0;
1974 }
1975 
1976