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