1 /*
2 ===========================================================================
3 Copyright (C) 1999-2005 Id Software, Inc.
4 Copyright (C) 2000-2006 Tim Angus
5 
6 This file is part of Tremulous.
7 
8 Tremulous is free software; you can redistribute it
9 and/or modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the License,
11 or (at your option) any later version.
12 
13 Tremulous is distributed in the hope that it will be
14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with Tremulous; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21 ===========================================================================
22 */
23 // tr_init.c -- functions that are not called every frame
24 
25 #include "tr_local.h"
26 
27 glconfig_t	glConfig;
28 glstate_t	glState;
29 
30 static void GfxInfo_f( void );
31 
32 cvar_t	*r_flareSize;
33 cvar_t	*r_flareFade;
34 
35 cvar_t	*r_railWidth;
36 cvar_t	*r_railCoreWidth;
37 cvar_t	*r_railSegmentLength;
38 
39 cvar_t	*r_ignoreFastPath;
40 
41 cvar_t	*r_verbose;
42 cvar_t	*r_ignore;
43 
44 cvar_t	*r_displayRefresh;
45 
46 cvar_t	*r_detailTextures;
47 
48 cvar_t	*r_znear;
49 
50 cvar_t	*r_smp;
51 cvar_t	*r_showSmp;
52 cvar_t	*r_skipBackEnd;
53 
54 cvar_t	*r_ignorehwgamma;
55 cvar_t	*r_measureOverdraw;
56 
57 cvar_t	*r_inGameVideo;
58 cvar_t	*r_fastsky;
59 cvar_t	*r_drawSun;
60 cvar_t	*r_dynamiclight;
61 cvar_t	*r_dlightBacks;
62 
63 cvar_t	*r_lodbias;
64 cvar_t	*r_lodscale;
65 
66 cvar_t	*r_norefresh;
67 cvar_t	*r_drawentities;
68 cvar_t	*r_drawworld;
69 cvar_t	*r_speeds;
70 cvar_t	*r_fullbright;
71 cvar_t	*r_novis;
72 cvar_t	*r_nocull;
73 cvar_t	*r_facePlaneCull;
74 cvar_t	*r_showcluster;
75 cvar_t	*r_nocurves;
76 
77 cvar_t	*r_allowExtensions;
78 
79 cvar_t	*r_ext_compressed_textures;
80 cvar_t	*r_ext_gamma_control;
81 cvar_t	*r_ext_multitexture;
82 cvar_t	*r_ext_compiled_vertex_array;
83 cvar_t	*r_ext_texture_env_add;
84 
85 cvar_t	*r_ignoreGLErrors;
86 cvar_t	*r_logFile;
87 
88 cvar_t	*r_stencilbits;
89 cvar_t	*r_depthbits;
90 cvar_t	*r_colorbits;
91 cvar_t	*r_stereo;
92 cvar_t	*r_primitives;
93 cvar_t	*r_texturebits;
94 
95 cvar_t	*r_drawBuffer;
96 cvar_t  *r_glDriver;
97 cvar_t	*r_lightmap;
98 cvar_t	*r_vertexLight;
99 cvar_t	*r_uiFullScreen;
100 cvar_t	*r_shadows;
101 cvar_t	*r_flares;
102 cvar_t	*r_mode;
103 cvar_t	*r_nobind;
104 cvar_t	*r_singleShader;
105 cvar_t	*r_roundImagesDown;
106 cvar_t	*r_colorMipLevels;
107 cvar_t	*r_picmip;
108 cvar_t	*r_showtris;
109 cvar_t	*r_showsky;
110 cvar_t	*r_shownormals;
111 cvar_t	*r_finish;
112 cvar_t	*r_clear;
113 cvar_t	*r_swapInterval;
114 cvar_t	*r_textureMode;
115 cvar_t	*r_offsetFactor;
116 cvar_t	*r_offsetUnits;
117 cvar_t	*r_gamma;
118 cvar_t	*r_intensity;
119 cvar_t	*r_lockpvs;
120 cvar_t	*r_noportals;
121 cvar_t	*r_portalOnly;
122 
123 cvar_t	*r_subdivisions;
124 cvar_t	*r_lodCurveError;
125 
126 cvar_t	*r_fullscreen;
127 
128 cvar_t	*r_customwidth;
129 cvar_t	*r_customheight;
130 cvar_t	*r_customaspect;
131 
132 cvar_t	*r_overBrightBits;
133 cvar_t	*r_mapOverBrightBits;
134 
135 cvar_t	*r_debugSurface;
136 cvar_t	*r_simpleMipMaps;
137 
138 cvar_t	*r_showImages;
139 
140 cvar_t	*r_ambientScale;
141 cvar_t	*r_directedScale;
142 cvar_t	*r_debugLight;
143 cvar_t	*r_debugSort;
144 cvar_t	*r_printShaders;
145 cvar_t	*r_saveFontData;
146 
147 cvar_t	*r_GLlibCoolDownMsec;
148 
149 cvar_t	*r_maxpolys;
150 int		max_polys;
151 cvar_t	*r_maxpolyverts;
152 int		max_polyverts;
153 
AssertCvarRange(cvar_t * cv,float minVal,float maxVal,qboolean shouldBeIntegral)154 static void AssertCvarRange( cvar_t *cv, float minVal, float maxVal, qboolean shouldBeIntegral )
155 {
156 	if ( shouldBeIntegral )
157 	{
158 		if ( ( int ) cv->value != cv->integer )
159 		{
160 			ri.Printf( PRINT_WARNING, "WARNING: cvar '%s' must be integral (%f)\n", cv->name, cv->value );
161 			ri.Cvar_Set( cv->name, va( "%d", cv->integer ) );
162 		}
163 	}
164 
165 	if ( cv->value < minVal )
166 	{
167 		ri.Printf( PRINT_WARNING, "WARNING: cvar '%s' out of range (%f < %f)\n", cv->name, cv->value, minVal );
168 		ri.Cvar_Set( cv->name, va( "%f", minVal ) );
169 	}
170 	else if ( cv->value > maxVal )
171 	{
172 		ri.Printf( PRINT_WARNING, "WARNING: cvar '%s' out of range (%f > %f)\n", cv->name, cv->value, maxVal );
173 		ri.Cvar_Set( cv->name, va( "%f", maxVal ) );
174 	}
175 }
176 
177 
178 #define GENERIC_HW_R_PICMIP_DEFAULT				"0"
179 #define GENERIC_HW_R_TEXTUREMODE_DEFAULT	"GL_LINEAR_MIPMAP_LINEAR"
180 
181 /*
182 ==================
183 GL_ResolveHardwareType
184 
185 Chipset specific configuration
186 ==================
187 */
GL_ResolveHardwareType(void)188 void GL_ResolveHardwareType( void )
189 {
190 	char		buf[ 1024 ];
191 	cvar_t	*lastValidRenderer = ri.Cvar_Get(
192 			"r_lastValidRenderer", "(uninitialized)", CVAR_ARCHIVE );
193 
194 	Q_strncpyz( buf, glConfig.renderer_string, sizeof( buf ) );
195 	Q_strlwr( buf );
196 
197 	// NOTE: if changing cvars, do it within this block.  This allows them
198 	// to be overridden when testing driver fixes, etc. but only sets
199 	// them to their default state when the hardware is first installed/run.
200 	if( Q_stricmp( lastValidRenderer->string, glConfig.renderer_string ) )
201 	{
202 		glConfig.hardwareType = GLHW_GENERIC;
203 
204 		ri.Cvar_Set( "r_textureMode", GENERIC_HW_R_TEXTUREMODE_DEFAULT );
205 
206 		// VOODOO GRAPHICS w/ 2MB
207 		if ( strstr( buf, "voodoo graphics/1 tmu/2 mb" ) )
208 		{
209 			ri.Cvar_Set( "r_picmip", "2" );
210 			ri.Cvar_Get( "r_picmip", "1", CVAR_ARCHIVE | CVAR_LATCH );
211 		}
212 		else
213 		{
214 			ri.Cvar_Set( "r_picmip", GENERIC_HW_R_PICMIP_DEFAULT );
215 
216 			if ( strstr( buf, "rage 128" ) || strstr( buf, "rage128" ) )
217 			{
218 				ri.Cvar_Set( "r_finish", "0" );
219 			}
220 			// Savage3D and Savage4 should always have trilinear enabled
221 			else if ( strstr( buf, "savage3d" ) || strstr( buf, "s3 savage4" ) )
222 			{
223 				ri.Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_LINEAR" );
224 			}
225 		}
226 	}
227 
228 	//
229 	// this is where hardware specific workarounds that should be
230 	// detected/initialized every startup should go.
231 	//
232 	if ( strstr( buf, "banshee" ) || strstr( buf, "voodoo3" ) )
233 	{
234 		glConfig.hardwareType = GLHW_3DFX_2D3D;
235 	}
236 	// VOODOO GRAPHICS w/ 2MB
237 	else if ( strstr( buf, "voodoo graphics/1 tmu/2 mb" ) )
238 	{
239 	}
240 	else if ( strstr( buf, "glzicd" ) )
241 	{
242 	}
243 	else if ( strstr( buf, "rage pro" ) ||
244 			strstr( buf, "Rage Pro" ) ||
245 			strstr( buf, "ragepro" ) )
246 	{
247 		glConfig.hardwareType = GLHW_RAGEPRO;
248 	}
249 	else if ( strstr( buf, "rage 128" ) )
250 	{
251 	}
252 	else if ( strstr( buf, "permedia2" ) )
253 	{
254 		glConfig.hardwareType = GLHW_PERMEDIA2;
255 	}
256 	else if ( strstr( buf, "riva 128" ) )
257 	{
258 		glConfig.hardwareType = GLHW_RIVA128;
259 	}
260 	else if ( strstr( buf, "riva tnt " ) )
261 	{
262 	}
263 }
264 
265 /*
266 ** InitOpenGL
267 **
268 ** This function is responsible for initializing a valid OpenGL subsystem.  This
269 ** is done by calling GLimp_Init (which gives us a working OGL subsystem) then
270 ** setting variables, checking GL constants, and reporting the gfx system config
271 ** to the user.
272 */
InitOpenGL(void)273 static void InitOpenGL( void )
274 {
275 	char renderer_buffer[1024];
276 
277 	//
278 	// initialize OS specific portions of the renderer
279 	//
280 	// GLimp_Init directly or indirectly references the following cvars:
281 	//		- r_fullscreen
282 	//		- r_glDriver
283 	//		- r_mode
284 	//		- r_(color|depth|stencil)bits
285 	//		- r_ignorehwgamma
286 	//		- r_gamma
287 	//
288 
289 	if ( glConfig.vidWidth == 0 )
290 	{
291 		GLint		temp;
292 
293 		GLimp_Init();
294 
295 		strcpy( renderer_buffer, glConfig.renderer_string );
296 		Q_strlwr( renderer_buffer );
297 
298 		// OpenGL driver constants
299 		qglGetIntegerv( GL_MAX_TEXTURE_SIZE, &temp );
300 		glConfig.maxTextureSize = temp;
301 
302 		// stubbed or broken drivers may have reported 0...
303 		if ( glConfig.maxTextureSize <= 0 )
304 		{
305 			glConfig.maxTextureSize = 0;
306 		}
307 	}
308 
309 	// init command buffers and SMP
310 	R_InitCommandBuffers();
311 
312 	// print info
313 	GfxInfo_f();
314 
315 	// set default state
316 	GL_SetDefaultState();
317 }
318 
319 /*
320 ==================
321 GL_CheckErrors
322 ==================
323 */
GL_CheckErrors(void)324 void GL_CheckErrors( void ) {
325     int		err;
326     char	s[64];
327 
328     err = qglGetError();
329     if ( err == GL_NO_ERROR ) {
330         return;
331     }
332     if ( r_ignoreGLErrors->integer ) {
333         return;
334     }
335     switch( err ) {
336         case GL_INVALID_ENUM:
337             strcpy( s, "GL_INVALID_ENUM" );
338             break;
339         case GL_INVALID_VALUE:
340             strcpy( s, "GL_INVALID_VALUE" );
341             break;
342         case GL_INVALID_OPERATION:
343             strcpy( s, "GL_INVALID_OPERATION" );
344             break;
345         case GL_STACK_OVERFLOW:
346             strcpy( s, "GL_STACK_OVERFLOW" );
347             break;
348         case GL_STACK_UNDERFLOW:
349             strcpy( s, "GL_STACK_UNDERFLOW" );
350             break;
351         case GL_OUT_OF_MEMORY:
352             strcpy( s, "GL_OUT_OF_MEMORY" );
353             break;
354         default:
355             Com_sprintf( s, sizeof(s), "%i", err);
356             break;
357     }
358 
359     ri.Error( ERR_FATAL, "GL_CheckErrors: %s", s );
360 }
361 
362 
363 /*
364 ** R_GetModeInfo
365 */
366 typedef struct vidmode_s
367 {
368     const char *description;
369     int         width, height;
370 	float		pixelAspect;		// pixel width / height
371 } vidmode_t;
372 
373 vidmode_t r_vidModes[] =
374 {
375     { "Mode  0: 320x240",		320,	240,	1 },
376     { "Mode  1: 400x300",		400,	300,	1 },
377     { "Mode  2: 512x384",		512,	384,	1 },
378     { "Mode  3: 640x480",		640,	480,	1 },
379     { "Mode  4: 800x600",		800,	600,	1 },
380     { "Mode  5: 960x720",		960,	720,	1 },
381     { "Mode  6: 1024x768",		1024,	768,	1 },
382     { "Mode  7: 1152x864",		1152,	864,	1 },
383     { "Mode  8: 1280x1024",		1280,	1024,	1 },
384     { "Mode  9: 1600x1200",		1600,	1200,	1 },
385     { "Mode 10: 2048x1536",		2048,	1536,	1 },
386     { "Mode 11: 856x480 (wide)",856,	480,	1 }
387 };
388 static int	s_numVidModes = ( sizeof( r_vidModes ) / sizeof( r_vidModes[0] ) );
389 
R_GetModeInfo(int * width,int * height,float * windowAspect,int mode)390 qboolean R_GetModeInfo( int *width, int *height, float *windowAspect, int mode ) {
391 	vidmode_t	*vm;
392 
393     if ( mode < -1 ) {
394         return qfalse;
395 	}
396 	if ( mode >= s_numVidModes ) {
397 		return qfalse;
398 	}
399 
400 	if ( mode == -1 ) {
401 		*width = r_customwidth->integer;
402 		*height = r_customheight->integer;
403 		*windowAspect = r_customaspect->value;
404 		return qtrue;
405 	}
406 
407 	vm = &r_vidModes[mode];
408 
409     *width  = vm->width;
410     *height = vm->height;
411     *windowAspect = (float)vm->width / ( vm->height * vm->pixelAspect );
412 
413     return qtrue;
414 }
415 
416 /*
417 ** R_ModeList_f
418 */
R_ModeList_f(void)419 static void R_ModeList_f( void )
420 {
421 	int i;
422 
423 	ri.Printf( PRINT_ALL, "\n" );
424 	for ( i = 0; i < s_numVidModes; i++ )
425 	{
426 		ri.Printf( PRINT_ALL, "%s\n", r_vidModes[i].description );
427 	}
428 	ri.Printf( PRINT_ALL, "\n" );
429 }
430 
431 
432 /*
433 ==============================================================================
434 
435 						SCREEN SHOTS
436 
437 NOTE TTimo
438 some thoughts about the screenshots system:
439 screenshots get written in fs_homepath + fs_gamedir
440 vanilla q3 .. baseq3/screenshots/ *.tga
441 team arena .. missionpack/screenshots/ *.tga
442 
443 two commands: "screenshot" and "screenshotJPEG"
444 we use statics to store a count and start writing the first screenshot/screenshot????.tga (.jpg) available
445 (with FS_FileExists / FS_FOpenFileWrite calls)
446 FIXME: the statics don't get a reinit between fs_game changes
447 
448 ==============================================================================
449 */
450 
451 /*
452 ==================
453 RB_TakeScreenshot
454 ==================
455 */
RB_TakeScreenshot(int x,int y,int width,int height,char * fileName)456 void RB_TakeScreenshot( int x, int y, int width, int height, char *fileName ) {
457 	byte		*buffer;
458 	int			i, c, temp;
459 
460 	buffer = ri.Hunk_AllocateTempMemory(glConfig.vidWidth*glConfig.vidHeight*3+18);
461 
462 	Com_Memset (buffer, 0, 18);
463 	buffer[2] = 2;		// uncompressed type
464 	buffer[12] = width & 255;
465 	buffer[13] = width >> 8;
466 	buffer[14] = height & 255;
467 	buffer[15] = height >> 8;
468 	buffer[16] = 24;	// pixel size
469 
470 	qglReadPixels( x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer+18 );
471 
472 	// swap rgb to bgr
473 	c = 18 + width * height * 3;
474 	for (i=18 ; i<c ; i+=3) {
475 		temp = buffer[i];
476 		buffer[i] = buffer[i+2];
477 		buffer[i+2] = temp;
478 	}
479 
480 	// gamma correct
481 	if ( ( tr.overbrightBits > 0 ) && glConfig.deviceSupportsGamma ) {
482 		R_GammaCorrect( buffer + 18, glConfig.vidWidth * glConfig.vidHeight * 3 );
483 	}
484 
485 	ri.FS_WriteFile( fileName, buffer, c );
486 
487 	ri.Hunk_FreeTempMemory( buffer );
488 }
489 
490 /*
491 ==================
492 RB_TakeScreenshotJPEG
493 ==================
494 */
RB_TakeScreenshotJPEG(int x,int y,int width,int height,char * fileName)495 void RB_TakeScreenshotJPEG( int x, int y, int width, int height, char *fileName ) {
496 	byte		*buffer;
497 
498 	buffer = ri.Hunk_AllocateTempMemory(glConfig.vidWidth*glConfig.vidHeight*4);
499 
500 	qglReadPixels( x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer );
501 
502 	// gamma correct
503 	if ( ( tr.overbrightBits > 0 ) && glConfig.deviceSupportsGamma ) {
504 		R_GammaCorrect( buffer, glConfig.vidWidth * glConfig.vidHeight * 4 );
505 	}
506 
507 	ri.FS_WriteFile( fileName, buffer, 1 );		// create path
508 	SaveJPG( fileName, 95, glConfig.vidWidth, glConfig.vidHeight, buffer);
509 
510 	ri.Hunk_FreeTempMemory( buffer );
511 }
512 
513 /*
514 ==================
515 RB_TakeScreenshotCmd
516 ==================
517 */
RB_TakeScreenshotCmd(const void * data)518 const void *RB_TakeScreenshotCmd( const void *data ) {
519 	const screenshotCommand_t	*cmd;
520 
521 	cmd = (const screenshotCommand_t *)data;
522 
523 	if (cmd->jpeg)
524 		RB_TakeScreenshotJPEG( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName);
525 	else
526 		RB_TakeScreenshot( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName);
527 
528 	return (const void *)(cmd + 1);
529 }
530 
531 /*
532 ==================
533 R_TakeScreenshot
534 ==================
535 */
R_TakeScreenshot(int x,int y,int width,int height,char * name,qboolean jpeg)536 void R_TakeScreenshot( int x, int y, int width, int height, char *name, qboolean jpeg ) {
537 	static char	fileName[MAX_OSPATH]; // bad things if two screenshots per frame?
538 	screenshotCommand_t	*cmd;
539 
540 	cmd = R_GetCommandBuffer( sizeof( *cmd ) );
541 	if ( !cmd ) {
542 		return;
543 	}
544 	cmd->commandId = RC_SCREENSHOT;
545 
546 	cmd->x = x;
547 	cmd->y = y;
548 	cmd->width = width;
549 	cmd->height = height;
550 	Q_strncpyz( fileName, name, sizeof(fileName) );
551 	cmd->fileName = fileName;
552 	cmd->jpeg = jpeg;
553 }
554 
555 /*
556 ==================
557 R_ScreenshotFilename
558 ==================
559 */
R_ScreenshotFilename(int lastNumber,char * fileName)560 void R_ScreenshotFilename( int lastNumber, char *fileName ) {
561 	int		a,b,c,d;
562 
563 	if ( lastNumber < 0 || lastNumber > 9999 ) {
564 		Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot9999.tga" );
565 		return;
566 	}
567 
568 	a = lastNumber / 1000;
569 	lastNumber -= a*1000;
570 	b = lastNumber / 100;
571 	lastNumber -= b*100;
572 	c = lastNumber / 10;
573 	lastNumber -= c*10;
574 	d = lastNumber;
575 
576 	Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot%i%i%i%i.tga"
577 		, a, b, c, d );
578 }
579 
580 /*
581 ==================
582 R_ScreenshotFilename
583 ==================
584 */
R_ScreenshotFilenameJPEG(int lastNumber,char * fileName)585 void R_ScreenshotFilenameJPEG( int lastNumber, char *fileName ) {
586 	int		a,b,c,d;
587 
588 	if ( lastNumber < 0 || lastNumber > 9999 ) {
589 		Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot9999.jpg" );
590 		return;
591 	}
592 
593 	a = lastNumber / 1000;
594 	lastNumber -= a*1000;
595 	b = lastNumber / 100;
596 	lastNumber -= b*100;
597 	c = lastNumber / 10;
598 	lastNumber -= c*10;
599 	d = lastNumber;
600 
601 	Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot%i%i%i%i.jpg"
602 		, a, b, c, d );
603 }
604 
605 /*
606 ====================
607 R_LevelShot
608 
609 levelshots are specialized 128*128 thumbnails for
610 the menu system, sampled down from full screen distorted images
611 ====================
612 */
R_LevelShot(void)613 void R_LevelShot( void ) {
614 	char		checkname[MAX_OSPATH];
615 	byte		*buffer;
616 	byte		*source;
617 	byte		*src, *dst;
618 	int			x, y;
619 	int			r, g, b;
620 	float		xScale, yScale;
621 	int			xx, yy;
622 
623 	sprintf( checkname, "levelshots/%s.tga", tr.world->baseName );
624 
625 	source = ri.Hunk_AllocateTempMemory( glConfig.vidWidth * glConfig.vidHeight * 3 );
626 
627 	buffer = ri.Hunk_AllocateTempMemory( 128 * 128*3 + 18);
628 	Com_Memset (buffer, 0, 18);
629 	buffer[2] = 2;		// uncompressed type
630 	buffer[12] = 128;
631 	buffer[14] = 128;
632 	buffer[16] = 24;	// pixel size
633 
634 	qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_RGB, GL_UNSIGNED_BYTE, source );
635 
636 	// resample from source
637 	xScale = glConfig.vidWidth / 512.0f;
638 	yScale = glConfig.vidHeight / 384.0f;
639 	for ( y = 0 ; y < 128 ; y++ ) {
640 		for ( x = 0 ; x < 128 ; x++ ) {
641 			r = g = b = 0;
642 			for ( yy = 0 ; yy < 3 ; yy++ ) {
643 				for ( xx = 0 ; xx < 4 ; xx++ ) {
644 					src = source + 3 * ( glConfig.vidWidth * (int)( (y*3+yy)*yScale ) + (int)( (x*4+xx)*xScale ) );
645 					r += src[0];
646 					g += src[1];
647 					b += src[2];
648 				}
649 			}
650 			dst = buffer + 18 + 3 * ( y * 128 + x );
651 			dst[0] = b / 12;
652 			dst[1] = g / 12;
653 			dst[2] = r / 12;
654 		}
655 	}
656 
657 	// gamma correct
658 	if ( ( tr.overbrightBits > 0 ) && glConfig.deviceSupportsGamma ) {
659 		R_GammaCorrect( buffer + 18, 128 * 128 * 3 );
660 	}
661 
662 	ri.FS_WriteFile( checkname, buffer, 128 * 128*3 + 18 );
663 
664 	ri.Hunk_FreeTempMemory( buffer );
665 	ri.Hunk_FreeTempMemory( source );
666 
667 	ri.Printf( PRINT_ALL, "Wrote %s\n", checkname );
668 }
669 
670 /*
671 ==================
672 R_ScreenShot_f
673 
674 screenshot
675 screenshot [silent]
676 screenshot [levelshot]
677 screenshot [filename]
678 
679 Doesn't print the pacifier message if there is a second arg
680 ==================
681 */
R_ScreenShot_f(void)682 void R_ScreenShot_f (void) {
683 	char	checkname[MAX_OSPATH];
684 	static	int	lastNumber = -1;
685 	qboolean	silent;
686 
687 	if ( !strcmp( ri.Cmd_Argv(1), "levelshot" ) ) {
688 		R_LevelShot();
689 		return;
690 	}
691 
692 	if ( !strcmp( ri.Cmd_Argv(1), "silent" ) ) {
693 		silent = qtrue;
694 	} else {
695 		silent = qfalse;
696 	}
697 
698 	if ( ri.Cmd_Argc() == 2 && !silent ) {
699 		// explicit filename
700 		Com_sprintf( checkname, MAX_OSPATH, "screenshots/%s.tga", ri.Cmd_Argv( 1 ) );
701 	} else {
702 		// scan for a free filename
703 
704 		// if we have saved a previous screenshot, don't scan
705 		// again, because recording demo avis can involve
706 		// thousands of shots
707 		if ( lastNumber == -1 ) {
708 			lastNumber = 0;
709 		}
710 		// scan for a free number
711 		for ( ; lastNumber <= 9999 ; lastNumber++ ) {
712 			R_ScreenshotFilename( lastNumber, checkname );
713 
714       if (!ri.FS_FileExists( checkname ))
715       {
716         break; // file doesn't exist
717       }
718 		}
719 
720 		if ( lastNumber >= 9999 ) {
721 			ri.Printf (PRINT_ALL, "ScreenShot: Couldn't create a file\n");
722 			return;
723  		}
724 
725 		lastNumber++;
726 	}
727 
728 	R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, qfalse );
729 
730 	if ( !silent ) {
731 		ri.Printf (PRINT_ALL, "Wrote %s\n", checkname);
732 	}
733 }
734 
R_ScreenShotJPEG_f(void)735 void R_ScreenShotJPEG_f (void) {
736 	char		checkname[MAX_OSPATH];
737 	static	int	lastNumber = -1;
738 	qboolean	silent;
739 
740 	if ( !strcmp( ri.Cmd_Argv(1), "levelshot" ) ) {
741 		R_LevelShot();
742 		return;
743 	}
744 
745 	if ( !strcmp( ri.Cmd_Argv(1), "silent" ) ) {
746 		silent = qtrue;
747 	} else {
748 		silent = qfalse;
749 	}
750 
751 	if ( ri.Cmd_Argc() == 2 && !silent ) {
752 		// explicit filename
753 		Com_sprintf( checkname, MAX_OSPATH, "screenshots/%s.jpg", ri.Cmd_Argv( 1 ) );
754 	} else {
755 		// scan for a free filename
756 
757 		// if we have saved a previous screenshot, don't scan
758 		// again, because recording demo avis can involve
759 		// thousands of shots
760 		if ( lastNumber == -1 ) {
761 			lastNumber = 0;
762 		}
763 		// scan for a free number
764 		for ( ; lastNumber <= 9999 ; lastNumber++ ) {
765 			R_ScreenshotFilenameJPEG( lastNumber, checkname );
766 
767       if (!ri.FS_FileExists( checkname ))
768       {
769         break; // file doesn't exist
770       }
771 		}
772 
773 		if ( lastNumber == 10000 ) {
774 			ri.Printf (PRINT_ALL, "ScreenShot: Couldn't create a file\n");
775 			return;
776  		}
777 
778 		lastNumber++;
779 	}
780 
781 	R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, qtrue );
782 
783 	if ( !silent ) {
784 		ri.Printf (PRINT_ALL, "Wrote %s\n", checkname);
785 	}
786 }
787 
788 //============================================================================
789 
790 /*
791 ==================
792 RB_TakeVideoFrameCmd
793 ==================
794 */
RB_TakeVideoFrameCmd(const void * data)795 const void *RB_TakeVideoFrameCmd( const void *data )
796 {
797 	const videoFrameCommand_t	*cmd;
798 	int												frameSize;
799 	int												i;
800 
801 	cmd = (const videoFrameCommand_t *)data;
802 
803 	qglReadPixels( 0, 0, cmd->width, cmd->height, GL_RGBA,
804 			GL_UNSIGNED_BYTE, cmd->captureBuffer );
805 
806 	// gamma correct
807 	if( ( tr.overbrightBits > 0 ) && glConfig.deviceSupportsGamma )
808 		R_GammaCorrect( cmd->captureBuffer, cmd->width * cmd->height * 4 );
809 
810 	if( cmd->motionJpeg )
811 	{
812 		frameSize = SaveJPGToBuffer( cmd->encodeBuffer, 95,
813 				cmd->width, cmd->height, cmd->captureBuffer );
814 	}
815 	else
816 	{
817 		frameSize = cmd->width * cmd->height * 4;
818 
819 		// Vertically flip the image
820 		for( i = 0; i < cmd->height; i++ )
821 		{
822 			Com_Memcpy( &cmd->encodeBuffer[ i * ( cmd->width * 4 ) ],
823 					&cmd->captureBuffer[ ( cmd->height - i - 1 ) * ( cmd->width * 4 ) ],
824 					cmd->width * 4 );
825 		}
826 	}
827 
828 	ri.CL_WriteAVIVideoFrame( cmd->encodeBuffer, frameSize );
829 
830 	return (const void *)(cmd + 1);
831 }
832 
833 //============================================================================
834 
835 /*
836 ** GL_SetDefaultState
837 */
GL_SetDefaultState(void)838 void GL_SetDefaultState( void )
839 {
840 	qglClearDepth( 1.0f );
841 
842 	qglCullFace(GL_FRONT);
843 
844 	qglColor4f (1,1,1,1);
845 
846 	// initialize downstream texture unit if we're running
847 	// in a multitexture environment
848 	if ( qglActiveTextureARB ) {
849 		GL_SelectTexture( 1 );
850 		GL_TextureMode( r_textureMode->string );
851 		GL_TexEnv( GL_MODULATE );
852 		qglDisable( GL_TEXTURE_2D );
853 		GL_SelectTexture( 0 );
854 	}
855 
856 	qglEnable(GL_TEXTURE_2D);
857 	GL_TextureMode( r_textureMode->string );
858 	GL_TexEnv( GL_MODULATE );
859 
860 	qglShadeModel( GL_SMOOTH );
861 	qglDepthFunc( GL_LEQUAL );
862 
863 	// the vertex array is always enabled, but the color and texture
864 	// arrays are enabled and disabled around the compiled vertex array call
865 	qglEnableClientState (GL_VERTEX_ARRAY);
866 
867 	//
868 	// make sure our GL state vector is set correctly
869 	//
870 	glState.glStateBits = GLS_DEPTHTEST_DISABLE | GLS_DEPTHMASK_TRUE;
871 
872 	qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
873 	qglDepthMask( GL_TRUE );
874 	qglDisable( GL_DEPTH_TEST );
875 	qglEnable( GL_SCISSOR_TEST );
876 	qglDisable( GL_CULL_FACE );
877 	qglDisable( GL_BLEND );
878 }
879 
880 
881 /*
882 ================
883 GfxInfo_f
884 ================
885 */
GfxInfo_f(void)886 void GfxInfo_f( void )
887 {
888 	cvar_t *sys_cpustring = ri.Cvar_Get( "sys_cpustring", "", 0 );
889 	const char *enablestrings[] =
890 	{
891 		"disabled",
892 		"enabled"
893 	};
894 	const char *fsstrings[] =
895 	{
896 		"windowed",
897 		"fullscreen"
898 	};
899 
900 	ri.Printf( PRINT_ALL, "\nGL_VENDOR: %s\n", glConfig.vendor_string );
901 	ri.Printf( PRINT_ALL, "GL_RENDERER: %s\n", glConfig.renderer_string );
902 	ri.Printf( PRINT_ALL, "GL_VERSION: %s\n", glConfig.version_string );
903 	ri.Printf( PRINT_ALL, "GL_EXTENSIONS: %s\n", glConfig.extensions_string );
904 	ri.Printf( PRINT_ALL, "GL_MAX_TEXTURE_SIZE: %d\n", glConfig.maxTextureSize );
905 	ri.Printf( PRINT_ALL, "GL_MAX_ACTIVE_TEXTURES_ARB: %d\n", glConfig.maxActiveTextures );
906 	ri.Printf( PRINT_ALL, "\nPIXELFORMAT: color(%d-bits) Z(%d-bit) stencil(%d-bits)\n", glConfig.colorBits, glConfig.depthBits, glConfig.stencilBits );
907 	ri.Printf( PRINT_ALL, "MODE: %d, %d x %d %s hz:", r_mode->integer, glConfig.vidWidth, glConfig.vidHeight, fsstrings[r_fullscreen->integer == 1] );
908 	if ( glConfig.displayFrequency )
909 	{
910 		ri.Printf( PRINT_ALL, "%d\n", glConfig.displayFrequency );
911 	}
912 	else
913 	{
914 		ri.Printf( PRINT_ALL, "N/A\n" );
915 	}
916 	if ( glConfig.deviceSupportsGamma )
917 	{
918 		ri.Printf( PRINT_ALL, "GAMMA: hardware w/ %d overbright bits\n", tr.overbrightBits );
919 	}
920 	else
921 	{
922 		ri.Printf( PRINT_ALL, "GAMMA: software w/ %d overbright bits\n", tr.overbrightBits );
923 	}
924 	ri.Printf( PRINT_ALL, "CPU: %s\n", sys_cpustring->string );
925 
926 	// rendering primitives
927 	{
928 		int		primitives;
929 
930 		// default is to use triangles if compiled vertex arrays are present
931 		ri.Printf( PRINT_ALL, "rendering primitives: " );
932 		primitives = r_primitives->integer;
933 		if ( primitives == 0 ) {
934 			if ( qglLockArraysEXT ) {
935 				primitives = 2;
936 			} else {
937 				primitives = 1;
938 			}
939 		}
940 		if ( primitives == -1 ) {
941 			ri.Printf( PRINT_ALL, "none\n" );
942 		} else if ( primitives == 2 ) {
943 			ri.Printf( PRINT_ALL, "single glDrawElements\n" );
944 		} else if ( primitives == 1 ) {
945 			ri.Printf( PRINT_ALL, "multiple glArrayElement\n" );
946 		} else if ( primitives == 3 ) {
947 			ri.Printf( PRINT_ALL, "multiple glColor4ubv + glTexCoord2fv + glVertex3fv\n" );
948 		}
949 	}
950 
951 	ri.Printf( PRINT_ALL, "texturemode: %s\n", r_textureMode->string );
952 	ri.Printf( PRINT_ALL, "picmip: %d\n", r_picmip->integer );
953 	ri.Printf( PRINT_ALL, "texture bits: %d\n", r_texturebits->integer );
954 	ri.Printf( PRINT_ALL, "multitexture: %s\n", enablestrings[qglActiveTextureARB != 0] );
955 	ri.Printf( PRINT_ALL, "compiled vertex arrays: %s\n", enablestrings[qglLockArraysEXT != 0 ] );
956 	ri.Printf( PRINT_ALL, "texenv add: %s\n", enablestrings[glConfig.textureEnvAddAvailable != 0] );
957 	ri.Printf( PRINT_ALL, "compressed textures: %s\n", enablestrings[glConfig.textureCompression!=TC_NONE] );
958 	if ( r_vertexLight->integer || glConfig.hardwareType == GLHW_PERMEDIA2 )
959 	{
960 		ri.Printf( PRINT_ALL, "HACK: using vertex lightmap approximation\n" );
961 	}
962 	if ( glConfig.hardwareType == GLHW_RAGEPRO )
963 	{
964 		ri.Printf( PRINT_ALL, "HACK: ragePro approximations\n" );
965 	}
966 	if ( glConfig.hardwareType == GLHW_RIVA128 )
967 	{
968 		ri.Printf( PRINT_ALL, "HACK: riva128 approximations\n" );
969 	}
970 	if ( glConfig.smpActive ) {
971 		ri.Printf( PRINT_ALL, "Using dual processor acceleration\n" );
972 	}
973 	if ( r_finish->integer ) {
974 		ri.Printf( PRINT_ALL, "Forcing glFinish\n" );
975 	}
976 }
977 
978 /*
979 ===============
980 R_Register
981 ===============
982 */
R_Register(void)983 void R_Register( void )
984 {
985 	//
986 	// latched and archived variables
987 	//
988 	r_glDriver = ri.Cvar_Get( "r_glDriver", OPENGL_DRIVER_NAME, CVAR_ARCHIVE | CVAR_LATCH );
989 	r_allowExtensions = ri.Cvar_Get( "r_allowExtensions", "1", CVAR_ARCHIVE | CVAR_LATCH );
990 	r_ext_compressed_textures = ri.Cvar_Get( "r_ext_compressed_textures", "0", CVAR_ARCHIVE | CVAR_LATCH );
991 	r_ext_gamma_control = ri.Cvar_Get( "r_ext_gamma_control", "1", CVAR_ARCHIVE | CVAR_LATCH );
992 	r_ext_multitexture = ri.Cvar_Get( "r_ext_multitexture", "1", CVAR_ARCHIVE | CVAR_LATCH );
993 	r_ext_compiled_vertex_array = ri.Cvar_Get( "r_ext_compiled_vertex_array", "1", CVAR_ARCHIVE | CVAR_LATCH);
994 	r_ext_texture_env_add = ri.Cvar_Get( "r_ext_texture_env_add", "0", CVAR_ARCHIVE | CVAR_LATCH);
995 
996 	r_picmip = ri.Cvar_Get ("r_picmip", GENERIC_HW_R_PICMIP_DEFAULT,
997 			CVAR_ARCHIVE | CVAR_LATCH );
998 	r_roundImagesDown = ri.Cvar_Get ("r_roundImagesDown", "1", CVAR_ARCHIVE | CVAR_LATCH );
999 	r_colorMipLevels = ri.Cvar_Get ("r_colorMipLevels", "0", CVAR_LATCH );
1000 	AssertCvarRange( r_picmip, 0, 16, qtrue );
1001 	r_detailTextures = ri.Cvar_Get( "r_detailtextures", "1", CVAR_ARCHIVE | CVAR_LATCH );
1002 	r_texturebits = ri.Cvar_Get( "r_texturebits", "0", CVAR_ARCHIVE | CVAR_LATCH );
1003 	r_colorbits = ri.Cvar_Get( "r_colorbits", "0", CVAR_ARCHIVE | CVAR_LATCH );
1004 	r_stereo = ri.Cvar_Get( "r_stereo", "0", CVAR_ARCHIVE | CVAR_LATCH );
1005 	r_stencilbits = ri.Cvar_Get( "r_stencilbits", "8", CVAR_ARCHIVE | CVAR_LATCH );
1006 	r_depthbits = ri.Cvar_Get( "r_depthbits", "0", CVAR_ARCHIVE | CVAR_LATCH );
1007 	r_overBrightBits = ri.Cvar_Get ("r_overBrightBits", "1", CVAR_ARCHIVE | CVAR_LATCH );
1008 	r_ignorehwgamma = ri.Cvar_Get( "r_ignorehwgamma", "0", CVAR_ARCHIVE | CVAR_LATCH);
1009 	r_mode = ri.Cvar_Get( "r_mode", "3", CVAR_ARCHIVE | CVAR_LATCH );
1010 #if USE_SDL_VIDEO
1011 	r_fullscreen = ri.Cvar_Get( "r_fullscreen", "1", CVAR_ARCHIVE );
1012 #else
1013 	r_fullscreen = ri.Cvar_Get( "r_fullscreen", "1", CVAR_ARCHIVE | CVAR_LATCH );
1014 #endif
1015 	r_customwidth = ri.Cvar_Get( "r_customwidth", "1600", CVAR_ARCHIVE | CVAR_LATCH );
1016 	r_customheight = ri.Cvar_Get( "r_customheight", "1024", CVAR_ARCHIVE | CVAR_LATCH );
1017 	r_customaspect = ri.Cvar_Get( "r_customaspect", "1", CVAR_ARCHIVE | CVAR_LATCH );
1018 	r_simpleMipMaps = ri.Cvar_Get( "r_simpleMipMaps", "1", CVAR_ARCHIVE | CVAR_LATCH );
1019 	r_vertexLight = ri.Cvar_Get( "r_vertexLight", "0", CVAR_ARCHIVE | CVAR_LATCH );
1020 	r_uiFullScreen = ri.Cvar_Get( "r_uifullscreen", "0", 0);
1021 	r_subdivisions = ri.Cvar_Get ("r_subdivisions", "4", CVAR_ARCHIVE | CVAR_LATCH);
1022 	r_smp = ri.Cvar_Get( "r_smp", "0", CVAR_ARCHIVE | CVAR_LATCH);
1023 	r_ignoreFastPath = ri.Cvar_Get( "r_ignoreFastPath", "1", CVAR_ARCHIVE | CVAR_LATCH );
1024 
1025 	//
1026 	// temporary latched variables that can only change over a restart
1027 	//
1028 	r_displayRefresh = ri.Cvar_Get( "r_displayRefresh", "0", CVAR_LATCH );
1029 	AssertCvarRange( r_displayRefresh, 0, 200, qtrue );
1030 	r_fullbright = ri.Cvar_Get ("r_fullbright", "0", CVAR_LATCH|CVAR_CHEAT );
1031 	r_mapOverBrightBits = ri.Cvar_Get ("r_mapOverBrightBits", "2", CVAR_LATCH );
1032 	r_intensity = ri.Cvar_Get ("r_intensity", "1", CVAR_LATCH );
1033 	r_singleShader = ri.Cvar_Get ("r_singleShader", "0", CVAR_CHEAT | CVAR_LATCH );
1034 
1035 	//
1036 	// archived variables that can change at any time
1037 	//
1038 	r_lodCurveError = ri.Cvar_Get( "r_lodCurveError", "250", CVAR_ARCHIVE|CVAR_CHEAT );
1039 	r_lodbias = ri.Cvar_Get( "r_lodbias", "0", CVAR_ARCHIVE );
1040 	r_flares = ri.Cvar_Get ("r_flares", "0", CVAR_ARCHIVE );
1041 	r_znear = ri.Cvar_Get( "r_znear", "1", CVAR_CHEAT );
1042 	AssertCvarRange( r_znear, 0.001f, 200, qtrue );
1043 	r_ignoreGLErrors = ri.Cvar_Get( "r_ignoreGLErrors", "1", CVAR_ARCHIVE );
1044 	r_fastsky = ri.Cvar_Get( "r_fastsky", "0", CVAR_ARCHIVE );
1045 	r_inGameVideo = ri.Cvar_Get( "r_inGameVideo", "1", CVAR_ARCHIVE );
1046 	r_drawSun = ri.Cvar_Get( "r_drawSun", "0", CVAR_ARCHIVE );
1047 	r_dynamiclight = ri.Cvar_Get( "r_dynamiclight", "1", CVAR_ARCHIVE );
1048 	r_dlightBacks = ri.Cvar_Get( "r_dlightBacks", "1", CVAR_ARCHIVE );
1049 	r_finish = ri.Cvar_Get ("r_finish", "0", CVAR_ARCHIVE);
1050 	r_textureMode = ri.Cvar_Get( "r_textureMode",
1051 			GENERIC_HW_R_TEXTUREMODE_DEFAULT, CVAR_ARCHIVE );
1052 	r_swapInterval = ri.Cvar_Get( "r_swapInterval", "0", CVAR_ARCHIVE );
1053 	r_gamma = ri.Cvar_Get( "r_gamma", "1", CVAR_ARCHIVE );
1054 	r_facePlaneCull = ri.Cvar_Get ("r_facePlaneCull", "1", CVAR_ARCHIVE );
1055 
1056 	r_railWidth = ri.Cvar_Get( "r_railWidth", "16", CVAR_ARCHIVE );
1057 	r_railCoreWidth = ri.Cvar_Get( "r_railCoreWidth", "6", CVAR_ARCHIVE );
1058 	r_railSegmentLength = ri.Cvar_Get( "r_railSegmentLength", "32", CVAR_ARCHIVE );
1059 
1060 	r_primitives = ri.Cvar_Get( "r_primitives", "0", CVAR_ARCHIVE );
1061 
1062 	r_ambientScale = ri.Cvar_Get( "r_ambientScale", "0.6", CVAR_CHEAT );
1063 	r_directedScale = ri.Cvar_Get( "r_directedScale", "1", CVAR_CHEAT );
1064 
1065 	//
1066 	// temporary variables that can change at any time
1067 	//
1068 	r_showImages = ri.Cvar_Get( "r_showImages", "0", CVAR_TEMP );
1069 
1070 	r_debugLight = ri.Cvar_Get( "r_debuglight", "0", CVAR_TEMP );
1071 	r_debugSort = ri.Cvar_Get( "r_debugSort", "0", CVAR_CHEAT );
1072 	r_printShaders = ri.Cvar_Get( "r_printShaders", "0", 0 );
1073 	r_saveFontData = ri.Cvar_Get( "r_saveFontData", "0", 0 );
1074 
1075 	r_nocurves = ri.Cvar_Get ("r_nocurves", "0", CVAR_CHEAT );
1076 	r_drawworld = ri.Cvar_Get ("r_drawworld", "1", CVAR_CHEAT );
1077 	r_lightmap = ri.Cvar_Get ("r_lightmap", "0", 0 );
1078 	r_portalOnly = ri.Cvar_Get ("r_portalOnly", "0", CVAR_CHEAT );
1079 
1080 	r_flareSize = ri.Cvar_Get ("r_flareSize", "40", CVAR_CHEAT);
1081 	r_flareFade = ri.Cvar_Get ("r_flareFade", "7", CVAR_CHEAT);
1082 
1083 	r_showSmp = ri.Cvar_Get ("r_showSmp", "0", CVAR_CHEAT);
1084 	r_skipBackEnd = ri.Cvar_Get ("r_skipBackEnd", "0", CVAR_CHEAT);
1085 
1086 	r_measureOverdraw = ri.Cvar_Get( "r_measureOverdraw", "0", CVAR_CHEAT );
1087 	r_lodscale = ri.Cvar_Get( "r_lodscale", "5", CVAR_CHEAT );
1088 	r_norefresh = ri.Cvar_Get ("r_norefresh", "0", CVAR_CHEAT);
1089 	r_drawentities = ri.Cvar_Get ("r_drawentities", "1", CVAR_CHEAT );
1090 	r_ignore = ri.Cvar_Get( "r_ignore", "1", CVAR_CHEAT );
1091 	r_nocull = ri.Cvar_Get ("r_nocull", "0", CVAR_CHEAT);
1092 	r_novis = ri.Cvar_Get ("r_novis", "0", CVAR_CHEAT);
1093 	r_showcluster = ri.Cvar_Get ("r_showcluster", "0", CVAR_CHEAT);
1094 	r_speeds = ri.Cvar_Get ("r_speeds", "0", CVAR_CHEAT);
1095 	r_verbose = ri.Cvar_Get( "r_verbose", "0", CVAR_CHEAT );
1096 	r_logFile = ri.Cvar_Get( "r_logFile", "0", CVAR_CHEAT );
1097 	r_debugSurface = ri.Cvar_Get ("r_debugSurface", "0", CVAR_CHEAT);
1098 	r_nobind = ri.Cvar_Get ("r_nobind", "0", CVAR_CHEAT);
1099 	r_showtris = ri.Cvar_Get ("r_showtris", "0", CVAR_CHEAT);
1100 	r_showsky = ri.Cvar_Get ("r_showsky", "0", CVAR_CHEAT);
1101 	r_shownormals = ri.Cvar_Get ("r_shownormals", "0", CVAR_CHEAT);
1102 	r_clear = ri.Cvar_Get ("r_clear", "0", CVAR_CHEAT);
1103 	r_offsetFactor = ri.Cvar_Get( "r_offsetfactor", "-1", CVAR_CHEAT );
1104 	r_offsetUnits = ri.Cvar_Get( "r_offsetunits", "-2", CVAR_CHEAT );
1105 	r_drawBuffer = ri.Cvar_Get( "r_drawBuffer", "GL_BACK", CVAR_CHEAT );
1106 	r_lockpvs = ri.Cvar_Get ("r_lockpvs", "0", CVAR_CHEAT);
1107 	r_noportals = ri.Cvar_Get ("r_noportals", "0", CVAR_CHEAT);
1108 	r_shadows = ri.Cvar_Get( "cg_shadows", "1", 0 );
1109 
1110 	r_maxpolys = ri.Cvar_Get( "r_maxpolys", va("%d", MAX_POLYS), 0);
1111 	r_maxpolyverts = ri.Cvar_Get( "r_maxpolyverts", va("%d", MAX_POLYVERTS), 0);
1112 
1113 	r_GLlibCoolDownMsec = ri.Cvar_Get( "r_GLlibCoolDownMsec", "0", CVAR_ARCHIVE );
1114 
1115 	// make sure all the commands added here are also
1116 	// removed in R_Shutdown
1117 	ri.Cmd_AddCommand( "imagelist", R_ImageList_f );
1118 	ri.Cmd_AddCommand( "shaderlist", R_ShaderList_f );
1119 	ri.Cmd_AddCommand( "skinlist", R_SkinList_f );
1120 	ri.Cmd_AddCommand( "modellist", R_Modellist_f );
1121 	ri.Cmd_AddCommand( "modelist", R_ModeList_f );
1122 	ri.Cmd_AddCommand( "screenshot", R_ScreenShot_f );
1123 	ri.Cmd_AddCommand( "screenshotJPEG", R_ScreenShotJPEG_f );
1124 	ri.Cmd_AddCommand( "gfxinfo", GfxInfo_f );
1125 }
1126 
1127 /*
1128 ===============
1129 R_Init
1130 ===============
1131 */
R_Init(void)1132 void R_Init( void ) {
1133 	int	err;
1134 	int i;
1135 	byte *ptr;
1136 
1137 	ri.Printf( PRINT_ALL, "----- R_Init -----\n" );
1138 
1139 	// clear all our internal state
1140 	Com_Memset( &tr, 0, sizeof( tr ) );
1141 	Com_Memset( &backEnd, 0, sizeof( backEnd ) );
1142 	Com_Memset( &tess, 0, sizeof( tess ) );
1143 
1144 //	Swap_Init();
1145 
1146 	if ( (int)tess.xyz & 15 ) {
1147 		Com_Printf( "WARNING: tess.xyz not 16 byte aligned\n" );
1148 	}
1149 	Com_Memset( tess.constantColor255, 255, sizeof( tess.constantColor255 ) );
1150 
1151 	//
1152 	// init function tables
1153 	//
1154 	for ( i = 0; i < FUNCTABLE_SIZE; i++ )
1155 	{
1156 		tr.sinTable[i]		= sin( DEG2RAD( i * 360.0f / ( ( float ) ( FUNCTABLE_SIZE - 1 ) ) ) );
1157 		tr.squareTable[i]	= ( i < FUNCTABLE_SIZE/2 ) ? 1.0f : -1.0f;
1158 		tr.sawToothTable[i] = (float)i / FUNCTABLE_SIZE;
1159 		tr.inverseSawToothTable[i] = 1.0f - tr.sawToothTable[i];
1160 
1161 		if ( i < FUNCTABLE_SIZE / 2 )
1162 		{
1163 			if ( i < FUNCTABLE_SIZE / 4 )
1164 			{
1165 				tr.triangleTable[i] = ( float ) i / ( FUNCTABLE_SIZE / 4 );
1166 			}
1167 			else
1168 			{
1169 				tr.triangleTable[i] = 1.0f - tr.triangleTable[i-FUNCTABLE_SIZE / 4];
1170 			}
1171 		}
1172 		else
1173 		{
1174 			tr.triangleTable[i] = -tr.triangleTable[i-FUNCTABLE_SIZE/2];
1175 		}
1176 	}
1177 
1178 	R_InitFogTable();
1179 
1180 	R_NoiseInit();
1181 
1182 	R_Register();
1183 
1184 	max_polys = r_maxpolys->integer;
1185 	if (max_polys < MAX_POLYS)
1186 		max_polys = MAX_POLYS;
1187 
1188 	max_polyverts = r_maxpolyverts->integer;
1189 	if (max_polyverts < MAX_POLYVERTS)
1190 		max_polyverts = MAX_POLYVERTS;
1191 
1192 	ptr = ri.Hunk_Alloc( sizeof( *backEndData[0] ) + sizeof(srfPoly_t) * max_polys + sizeof(polyVert_t) * max_polyverts, h_low);
1193 	backEndData[0] = (backEndData_t *) ptr;
1194 	backEndData[0]->polys = (srfPoly_t *) ((char *) ptr + sizeof( *backEndData[0] ));
1195 	backEndData[0]->polyVerts = (polyVert_t *) ((char *) ptr + sizeof( *backEndData[0] ) + sizeof(srfPoly_t) * max_polys);
1196 	if ( r_smp->integer ) {
1197 		ptr = ri.Hunk_Alloc( sizeof( *backEndData[1] ) + sizeof(srfPoly_t) * max_polys + sizeof(polyVert_t) * max_polyverts, h_low);
1198 		backEndData[1] = (backEndData_t *) ptr;
1199 		backEndData[1]->polys = (srfPoly_t *) ((char *) ptr + sizeof( *backEndData[1] ));
1200 		backEndData[1]->polyVerts = (polyVert_t *) ((char *) ptr + sizeof( *backEndData[1] ) + sizeof(srfPoly_t) * max_polys);
1201 	} else {
1202 		backEndData[1] = NULL;
1203 	}
1204 	R_ToggleSmpFrame();
1205 
1206 	InitOpenGL();
1207 
1208 	R_InitImages();
1209 
1210 	R_InitShaders();
1211 
1212 	R_InitSkins();
1213 
1214 	R_ModelInit();
1215 
1216 	R_InitFreeType();
1217 
1218 
1219 	err = qglGetError();
1220 	if ( err != GL_NO_ERROR )
1221 		ri.Printf (PRINT_ALL, "glGetError() = 0x%x\n", err);
1222 
1223 	ri.Printf( PRINT_ALL, "----- finished R_Init -----\n" );
1224 }
1225 
1226 /*
1227 ===============
1228 RE_Shutdown
1229 ===============
1230 */
RE_Shutdown(qboolean destroyWindow)1231 void RE_Shutdown( qboolean destroyWindow ) {
1232 
1233 	ri.Printf( PRINT_ALL, "RE_Shutdown( %i )\n", destroyWindow );
1234 
1235 	ri.Cmd_RemoveCommand ("modellist");
1236 	ri.Cmd_RemoveCommand ("screenshotJPEG");
1237 	ri.Cmd_RemoveCommand ("screenshot");
1238 	ri.Cmd_RemoveCommand ("imagelist");
1239 	ri.Cmd_RemoveCommand ("shaderlist");
1240 	ri.Cmd_RemoveCommand ("skinlist");
1241 	ri.Cmd_RemoveCommand ("gfxinfo");
1242 	ri.Cmd_RemoveCommand( "modelist" );
1243 	ri.Cmd_RemoveCommand( "shaderstate" );
1244 
1245 
1246 	if ( tr.registered ) {
1247 		R_SyncRenderThread();
1248 		R_ShutdownCommandBuffers();
1249 		R_DeleteTextures();
1250 	}
1251 
1252 	R_DoneFreeType();
1253 
1254 	// shut down platform specific OpenGL stuff
1255 	if ( destroyWindow ) {
1256 		GLimp_Shutdown();
1257 	}
1258 
1259 	tr.registered = qfalse;
1260 }
1261 
1262 
1263 /*
1264 =============
1265 RE_EndRegistration
1266 
1267 Touch all images to make sure they are resident
1268 =============
1269 */
RE_EndRegistration(void)1270 void RE_EndRegistration( void ) {
1271 	R_SyncRenderThread();
1272 	if (!Sys_LowPhysicalMemory()) {
1273 		RB_ShowImages();
1274 	}
1275 }
1276 
1277 
1278 /*
1279 @@@@@@@@@@@@@@@@@@@@@
1280 GetRefAPI
1281 
1282 @@@@@@@@@@@@@@@@@@@@@
1283 */
GetRefAPI(int apiVersion,refimport_t * rimp)1284 refexport_t *GetRefAPI ( int apiVersion, refimport_t *rimp ) {
1285 	static refexport_t	re;
1286 
1287 	ri = *rimp;
1288 
1289 	Com_Memset( &re, 0, sizeof( re ) );
1290 
1291 	if ( apiVersion != REF_API_VERSION ) {
1292 		ri.Printf(PRINT_ALL, "Mismatched REF_API_VERSION: expected %i, got %i\n",
1293 			REF_API_VERSION, apiVersion );
1294 		return NULL;
1295 	}
1296 
1297 	// the RE_ functions are Renderer Entry points
1298 
1299 	re.Shutdown = RE_Shutdown;
1300 
1301 	re.BeginRegistration = RE_BeginRegistration;
1302 	re.RegisterModel = RE_RegisterModel;
1303 	re.RegisterSkin = RE_RegisterSkin;
1304 	re.RegisterShader = RE_RegisterShader;
1305 	re.RegisterShaderNoMip = RE_RegisterShaderNoMip;
1306 	re.LoadWorld = RE_LoadWorldMap;
1307 	re.SetWorldVisData = RE_SetWorldVisData;
1308 	re.EndRegistration = RE_EndRegistration;
1309 
1310 	re.BeginFrame = RE_BeginFrame;
1311 	re.EndFrame = RE_EndFrame;
1312 
1313 	re.MarkFragments = R_MarkFragments;
1314 	re.LerpTag = R_LerpTag;
1315 	re.ModelBounds = R_ModelBounds;
1316 
1317 	re.ClearScene = RE_ClearScene;
1318 	re.AddRefEntityToScene = RE_AddRefEntityToScene;
1319 	re.AddPolyToScene = RE_AddPolyToScene;
1320 	re.LightForPoint = R_LightForPoint;
1321 	re.AddLightToScene = RE_AddLightToScene;
1322 	re.AddAdditiveLightToScene = RE_AddAdditiveLightToScene;
1323 	re.RenderScene = RE_RenderScene;
1324 
1325 	re.SetColor = RE_SetColor;
1326 	re.DrawStretchPic = RE_StretchPic;
1327 	re.DrawStretchRaw = RE_StretchRaw;
1328 	re.UploadCinematic = RE_UploadCinematic;
1329 
1330 	re.RegisterFont = RE_RegisterFont;
1331 	re.RemapShader = R_RemapShader;
1332 	re.GetEntityToken = R_GetEntityToken;
1333 	re.inPVS = R_inPVS;
1334 
1335 	re.TakeVideoFrame = RE_TakeVideoFrame;
1336 
1337 	return &re;
1338 }
1339