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