Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

tr_init.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 // tr_init.c -- functions that are not called every frame
00023 
00024 #include "tr_local.h"
00025 
00026 glconfig_t  glConfig;
00027 glstate_t   glState;
00028 
00029 static void GfxInfo_f( void );
00030 
00031 cvar_t  *r_flareSize;
00032 cvar_t  *r_flareFade;
00033 
00034 cvar_t  *r_railWidth;
00035 cvar_t  *r_railCoreWidth;
00036 cvar_t  *r_railSegmentLength;
00037 
00038 cvar_t  *r_ignoreFastPath;
00039 
00040 cvar_t  *r_verbose;
00041 cvar_t  *r_ignore;
00042 
00043 cvar_t  *r_displayRefresh;
00044 
00045 cvar_t  *r_detailTextures;
00046 
00047 cvar_t  *r_znear;
00048 
00049 cvar_t  *r_smp;
00050 cvar_t  *r_showSmp;
00051 cvar_t  *r_skipBackEnd;
00052 
00053 cvar_t  *r_ignorehwgamma;
00054 cvar_t  *r_measureOverdraw;
00055 
00056 cvar_t  *r_inGameVideo;
00057 cvar_t  *r_fastsky;
00058 cvar_t  *r_drawSun;
00059 cvar_t  *r_dynamiclight;
00060 cvar_t  *r_dlightBacks;
00061 
00062 cvar_t  *r_lodbias;
00063 cvar_t  *r_lodscale;
00064 
00065 cvar_t  *r_norefresh;
00066 cvar_t  *r_drawentities;
00067 cvar_t  *r_drawworld;
00068 cvar_t  *r_speeds;
00069 cvar_t  *r_fullbright;
00070 cvar_t  *r_novis;
00071 cvar_t  *r_nocull;
00072 cvar_t  *r_facePlaneCull;
00073 cvar_t  *r_showcluster;
00074 cvar_t  *r_nocurves;
00075 
00076 cvar_t  *r_allowExtensions;
00077 
00078 cvar_t  *r_ext_compressed_textures;
00079 cvar_t  *r_ext_gamma_control;
00080 cvar_t  *r_ext_multitexture;
00081 cvar_t  *r_ext_compiled_vertex_array;
00082 cvar_t  *r_ext_texture_env_add;
00083 
00084 cvar_t  *r_ignoreGLErrors;
00085 cvar_t  *r_logFile;
00086 
00087 cvar_t  *r_stencilbits;
00088 cvar_t  *r_depthbits;
00089 cvar_t  *r_colorbits;
00090 cvar_t  *r_stereo;
00091 cvar_t  *r_primitives;
00092 cvar_t  *r_texturebits;
00093 
00094 cvar_t  *r_drawBuffer;
00095 cvar_t  *r_glDriver;
00096 cvar_t  *r_lightmap;
00097 cvar_t  *r_vertexLight;
00098 cvar_t  *r_uiFullScreen;
00099 cvar_t  *r_shadows;
00100 cvar_t  *r_flares;
00101 cvar_t  *r_mode;
00102 cvar_t  *r_nobind;
00103 cvar_t  *r_singleShader;
00104 cvar_t  *r_roundImagesDown;
00105 cvar_t  *r_colorMipLevels;
00106 cvar_t  *r_picmip;
00107 cvar_t  *r_showtris;
00108 cvar_t  *r_showsky;
00109 cvar_t  *r_shownormals;
00110 cvar_t  *r_finish;
00111 cvar_t  *r_clear;
00112 cvar_t  *r_swapInterval;
00113 cvar_t  *r_textureMode;
00114 cvar_t  *r_offsetFactor;
00115 cvar_t  *r_offsetUnits;
00116 cvar_t  *r_gamma;
00117 cvar_t  *r_intensity;
00118 cvar_t  *r_lockpvs;
00119 cvar_t  *r_noportals;
00120 cvar_t  *r_portalOnly;
00121 
00122 cvar_t  *r_subdivisions;
00123 cvar_t  *r_lodCurveError;
00124 
00125 cvar_t  *r_fullscreen;
00126 
00127 cvar_t  *r_customwidth;
00128 cvar_t  *r_customheight;
00129 cvar_t  *r_customaspect;
00130 
00131 cvar_t  *r_overBrightBits;
00132 cvar_t  *r_mapOverBrightBits;
00133 
00134 cvar_t  *r_debugSurface;
00135 cvar_t  *r_simpleMipMaps;
00136 
00137 cvar_t  *r_showImages;
00138 
00139 cvar_t  *r_ambientScale;
00140 cvar_t  *r_directedScale;
00141 cvar_t  *r_debugLight;
00142 cvar_t  *r_debugSort;
00143 cvar_t  *r_printShaders;
00144 cvar_t  *r_saveFontData;
00145 
00146 cvar_t  *r_maxpolys;
00147 int     max_polys;
00148 cvar_t  *r_maxpolyverts;
00149 int     max_polyverts;
00150 
00151 void ( APIENTRY * qglMultiTexCoord2fARB )( GLenum texture, GLfloat s, GLfloat t );
00152 void ( APIENTRY * qglActiveTextureARB )( GLenum texture );
00153 void ( APIENTRY * qglClientActiveTextureARB )( GLenum texture );
00154 
00155 void ( APIENTRY * qglLockArraysEXT)( GLint, GLint);
00156 void ( APIENTRY * qglUnlockArraysEXT) ( void );
00157 
00158 static void AssertCvarRange( cvar_t *cv, float minVal, float maxVal, qboolean shouldBeIntegral )
00159 {
00160     if ( shouldBeIntegral )
00161     {
00162         if ( ( int ) cv->value != cv->integer )
00163         {
00164             ri.Printf( PRINT_WARNING, "WARNING: cvar '%s' must be integral (%f)\n", cv->name, cv->value );
00165             ri.Cvar_Set( cv->name, va( "%d", cv->integer ) );
00166         }
00167     }
00168 
00169     if ( cv->value < minVal )
00170     {
00171         ri.Printf( PRINT_WARNING, "WARNING: cvar '%s' out of range (%f < %f)\n", cv->name, cv->value, minVal );
00172         ri.Cvar_Set( cv->name, va( "%f", minVal ) );
00173     }
00174     else if ( cv->value > maxVal )
00175     {
00176         ri.Printf( PRINT_WARNING, "WARNING: cvar '%s' out of range (%f > %f)\n", cv->name, cv->value, maxVal );
00177         ri.Cvar_Set( cv->name, va( "%f", maxVal ) );
00178     }
00179 }
00180 
00181 
00182 /*
00183 ** InitOpenGL
00184 **
00185 ** This function is responsible for initializing a valid OpenGL subsystem.  This
00186 ** is done by calling GLimp_Init (which gives us a working OGL subsystem) then
00187 ** setting variables, checking GL constants, and reporting the gfx system config
00188 ** to the user.
00189 */
00190 static void InitOpenGL( void )
00191 {
00192     char renderer_buffer[1024];
00193 
00194     //
00195     // initialize OS specific portions of the renderer
00196     //
00197     // GLimp_Init directly or indirectly references the following cvars:
00198     //      - r_fullscreen
00199     //      - r_glDriver
00200     //      - r_mode
00201     //      - r_(color|depth|stencil)bits
00202     //      - r_ignorehwgamma
00203     //      - r_gamma
00204     //
00205     
00206     if ( glConfig.vidWidth == 0 )
00207     {
00208         GLint       temp;
00209         
00210         GLimp_Init();
00211 
00212         strcpy( renderer_buffer, glConfig.renderer_string );
00213         Q_strlwr( renderer_buffer );
00214 
00215         // OpenGL driver constants
00216         qglGetIntegerv( GL_MAX_TEXTURE_SIZE, &temp );
00217         glConfig.maxTextureSize = temp;
00218 
00219         // stubbed or broken drivers may have reported 0...
00220         if ( glConfig.maxTextureSize <= 0 ) 
00221         {
00222             glConfig.maxTextureSize = 0;
00223         }
00224     }
00225 
00226     // init command buffers and SMP
00227     R_InitCommandBuffers();
00228 
00229     // print info
00230     GfxInfo_f();
00231 
00232     // set default state
00233     GL_SetDefaultState();
00234 }
00235 
00236 /*
00237 ==================
00238 GL_CheckErrors
00239 ==================
00240 */
00241 void GL_CheckErrors( void ) {
00242     int     err;
00243     char    s[64];
00244 
00245     err = qglGetError();
00246     if ( err == GL_NO_ERROR ) {
00247         return;
00248     }
00249     if ( r_ignoreGLErrors->integer ) {
00250         return;
00251     }
00252     switch( err ) {
00253         case GL_INVALID_ENUM:
00254             strcpy( s, "GL_INVALID_ENUM" );
00255             break;
00256         case GL_INVALID_VALUE:
00257             strcpy( s, "GL_INVALID_VALUE" );
00258             break;
00259         case GL_INVALID_OPERATION:
00260             strcpy( s, "GL_INVALID_OPERATION" );
00261             break;
00262         case GL_STACK_OVERFLOW:
00263             strcpy( s, "GL_STACK_OVERFLOW" );
00264             break;
00265         case GL_STACK_UNDERFLOW:
00266             strcpy( s, "GL_STACK_UNDERFLOW" );
00267             break;
00268         case GL_OUT_OF_MEMORY:
00269             strcpy( s, "GL_OUT_OF_MEMORY" );
00270             break;
00271         default:
00272             Com_sprintf( s, sizeof(s), "%i", err);
00273             break;
00274     }
00275 
00276     ri.Error( ERR_FATAL, "GL_CheckErrors: %s", s );
00277 }
00278 
00279 
00280 /*
00281 ** R_GetModeInfo
00282 */
00283 typedef struct vidmode_s
00284 {
00285     const char *description;
00286     int         width, height;
00287     float       pixelAspect;        // pixel width / height
00288 } vidmode_t;
00289 
00290 vidmode_t r_vidModes[] =
00291 {
00292     { "Mode  0: 320x240",       320,    240,    1 },
00293     { "Mode  1: 400x300",       400,    300,    1 },
00294     { "Mode  2: 512x384",       512,    384,    1 },
00295     { "Mode  3: 640x480",       640,    480,    1 },
00296     { "Mode  4: 800x600",       800,    600,    1 },
00297     { "Mode  5: 960x720",       960,    720,    1 },
00298     { "Mode  6: 1024x768",      1024,   768,    1 },
00299     { "Mode  7: 1152x864",      1152,   864,    1 },
00300     { "Mode  8: 1280x1024",     1280,   1024,   1 },
00301     { "Mode  9: 1600x1200",     1600,   1200,   1 },
00302     { "Mode 10: 2048x1536",     2048,   1536,   1 },
00303     { "Mode 11: 856x480 (wide)",856,    480,    1 }
00304 };
00305 static int  s_numVidModes = ( sizeof( r_vidModes ) / sizeof( r_vidModes[0] ) );
00306 
00307 qboolean R_GetModeInfo( int *width, int *height, float *windowAspect, int mode ) {
00308     vidmode_t   *vm;
00309 
00310     if ( mode < -1 ) {
00311         return qfalse;
00312     }
00313     if ( mode >= s_numVidModes ) {
00314         return qfalse;
00315     }
00316 
00317     if ( mode == -1 ) {
00318         *width = r_customwidth->integer;
00319         *height = r_customheight->integer;
00320         *windowAspect = r_customaspect->value;
00321         return qtrue;
00322     }
00323 
00324     vm = &r_vidModes[mode];
00325 
00326     *width  = vm->width;
00327     *height = vm->height;
00328     *windowAspect = (float)vm->width / ( vm->height * vm->pixelAspect );
00329 
00330     return qtrue;
00331 }
00332 
00333 /*
00334 ** R_ModeList_f
00335 */
00336 static void R_ModeList_f( void )
00337 {
00338     int i;
00339 
00340     ri.Printf( PRINT_ALL, "\n" );
00341     for ( i = 0; i < s_numVidModes; i++ )
00342     {
00343         ri.Printf( PRINT_ALL, "%s\n", r_vidModes[i].description );
00344     }
00345     ri.Printf( PRINT_ALL, "\n" );
00346 }
00347 
00348 
00349 /* 
00350 ============================================================================== 
00351  
00352                         SCREEN SHOTS 
00353 
00354 NOTE TTimo
00355 some thoughts about the screenshots system:
00356 screenshots get written in fs_homepath + fs_gamedir
00357 vanilla q3 .. baseq3/screenshots/ *.tga
00358 team arena .. missionpack/screenshots/ *.tga
00359 
00360 two commands: "screenshot" and "screenshotJPEG"
00361 we use statics to store a count and start writing the first screenshot/screenshot????.tga (.jpg) available
00362 (with FS_FileExists / FS_FOpenFileWrite calls)
00363 FIXME: the statics don't get a reinit between fs_game changes
00364 
00365 ============================================================================== 
00366 */ 
00367 
00368 /* 
00369 ================== 
00370 RB_TakeScreenshot
00371 ================== 
00372 */  
00373 void RB_TakeScreenshot( int x, int y, int width, int height, char *fileName ) {
00374     byte        *buffer;
00375     int         i, c, temp;
00376         
00377     buffer = ri.Hunk_AllocateTempMemory(glConfig.vidWidth*glConfig.vidHeight*3+18);
00378 
00379     Com_Memset (buffer, 0, 18);
00380     buffer[2] = 2;      // uncompressed type
00381     buffer[12] = width & 255;
00382     buffer[13] = width >> 8;
00383     buffer[14] = height & 255;
00384     buffer[15] = height >> 8;
00385     buffer[16] = 24;    // pixel size
00386 
00387     qglReadPixels( x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer+18 ); 
00388 
00389     // swap rgb to bgr
00390     c = 18 + width * height * 3;
00391     for (i=18 ; i<c ; i+=3) {
00392         temp = buffer[i];
00393         buffer[i] = buffer[i+2];
00394         buffer[i+2] = temp;
00395     }
00396 
00397     // gamma correct
00398     if ( ( tr.overbrightBits > 0 ) && glConfig.deviceSupportsGamma ) {
00399         R_GammaCorrect( buffer + 18, glConfig.vidWidth * glConfig.vidHeight * 3 );
00400     }
00401 
00402     ri.FS_WriteFile( fileName, buffer, c );
00403 
00404     ri.Hunk_FreeTempMemory( buffer );
00405 }
00406 
00407 /* 
00408 ================== 
00409 RB_TakeScreenshotJPEG
00410 ================== 
00411 */  
00412 void RB_TakeScreenshotJPEG( int x, int y, int width, int height, char *fileName ) {
00413     byte        *buffer;
00414 
00415     buffer = ri.Hunk_AllocateTempMemory(glConfig.vidWidth*glConfig.vidHeight*4);
00416 
00417     qglReadPixels( x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer ); 
00418 
00419     // gamma correct
00420     if ( ( tr.overbrightBits > 0 ) && glConfig.deviceSupportsGamma ) {
00421         R_GammaCorrect( buffer, glConfig.vidWidth * glConfig.vidHeight * 4 );
00422     }
00423 
00424     ri.FS_WriteFile( fileName, buffer, 1 );     // create path
00425     SaveJPG( fileName, 95, glConfig.vidWidth, glConfig.vidHeight, buffer);
00426 
00427     ri.Hunk_FreeTempMemory( buffer );
00428 }
00429 
00430 /*
00431 ==================
00432 RB_TakeScreenshotCmd
00433 ==================
00434 */
00435 const void *RB_TakeScreenshotCmd( const void *data ) {
00436     const screenshotCommand_t   *cmd;
00437     
00438     cmd = (const screenshotCommand_t *)data;
00439     
00440     if (cmd->jpeg)
00441         RB_TakeScreenshotJPEG( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName);
00442     else
00443         RB_TakeScreenshot( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName);
00444     
00445     return (const void *)(cmd + 1); 
00446 }
00447 
00448 /*
00449 ==================
00450 R_TakeScreenshot
00451 ==================
00452 */
00453 void R_TakeScreenshot( int x, int y, int width, int height, char *name, qboolean jpeg ) {
00454     static char fileName[MAX_OSPATH]; // bad things if two screenshots per frame?
00455     screenshotCommand_t *cmd;
00456 
00457     cmd = R_GetCommandBuffer( sizeof( *cmd ) );
00458     if ( !cmd ) {
00459         return;
00460     }
00461     cmd->commandId = RC_SCREENSHOT;
00462 
00463     cmd->x = x;
00464     cmd->y = y;
00465     cmd->width = width;
00466     cmd->height = height;
00467     Q_strncpyz( fileName, name, sizeof(fileName) );
00468     cmd->fileName = fileName;
00469     cmd->jpeg = jpeg;
00470 }
00471 
00472 /* 
00473 ================== 
00474 R_ScreenshotFilename
00475 ================== 
00476 */  
00477 void R_ScreenshotFilename( int lastNumber, char *fileName ) {
00478     int     a,b,c,d;
00479 
00480     if ( lastNumber < 0 || lastNumber > 9999 ) {
00481         Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot9999.tga" );
00482         return;
00483     }
00484 
00485     a = lastNumber / 1000;
00486     lastNumber -= a*1000;
00487     b = lastNumber / 100;
00488     lastNumber -= b*100;
00489     c = lastNumber / 10;
00490     lastNumber -= c*10;
00491     d = lastNumber;
00492 
00493     Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot%i%i%i%i.tga"
00494         , a, b, c, d );
00495 }
00496 
00497 /* 
00498 ================== 
00499 R_ScreenshotFilename
00500 ================== 
00501 */  
00502 void R_ScreenshotFilenameJPEG( int lastNumber, char *fileName ) {
00503     int     a,b,c,d;
00504 
00505     if ( lastNumber < 0 || lastNumber > 9999 ) {
00506         Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot9999.jpg" );
00507         return;
00508     }
00509 
00510     a = lastNumber / 1000;
00511     lastNumber -= a*1000;
00512     b = lastNumber / 100;
00513     lastNumber -= b*100;
00514     c = lastNumber / 10;
00515     lastNumber -= c*10;
00516     d = lastNumber;
00517 
00518     Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot%i%i%i%i.jpg"
00519         , a, b, c, d );
00520 }
00521 
00522 /*
00523 ====================
00524 R_LevelShot
00525 
00526 levelshots are specialized 128*128 thumbnails for
00527 the menu system, sampled down from full screen distorted images
00528 ====================
00529 */
00530 void R_LevelShot( void ) {
00531     char        checkname[MAX_OSPATH];
00532     byte        *buffer;
00533     byte        *source;
00534     byte        *src, *dst;
00535     int         x, y;
00536     int         r, g, b;
00537     float       xScale, yScale;
00538     int         xx, yy;
00539 
00540     sprintf( checkname, "levelshots/%s.tga", tr.world->baseName );
00541 
00542     source = ri.Hunk_AllocateTempMemory( glConfig.vidWidth * glConfig.vidHeight * 3 );
00543 
00544     buffer = ri.Hunk_AllocateTempMemory( 128 * 128*3 + 18);
00545     Com_Memset (buffer, 0, 18);
00546     buffer[2] = 2;      // uncompressed type
00547     buffer[12] = 128;
00548     buffer[14] = 128;
00549     buffer[16] = 24;    // pixel size
00550 
00551     qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_RGB, GL_UNSIGNED_BYTE, source ); 
00552 
00553     // resample from source
00554     xScale = glConfig.vidWidth / 512.0f;
00555     yScale = glConfig.vidHeight / 384.0f;
00556     for ( y = 0 ; y < 128 ; y++ ) {
00557         for ( x = 0 ; x < 128 ; x++ ) {
00558             r = g = b = 0;
00559             for ( yy = 0 ; yy < 3 ; yy++ ) {
00560                 for ( xx = 0 ; xx < 4 ; xx++ ) {
00561                     src = source + 3 * ( glConfig.vidWidth * (int)( (y*3+yy)*yScale ) + (int)( (x*4+xx)*xScale ) );
00562                     r += src[0];
00563                     g += src[1];
00564                     b += src[2];
00565                 }
00566             }
00567             dst = buffer + 18 + 3 * ( y * 128 + x );
00568             dst[0] = b / 12;
00569             dst[1] = g / 12;
00570             dst[2] = r / 12;
00571         }
00572     }
00573 
00574     // gamma correct
00575     if ( ( tr.overbrightBits > 0 ) && glConfig.deviceSupportsGamma ) {
00576         R_GammaCorrect( buffer + 18, 128 * 128 * 3 );
00577     }
00578 
00579     ri.FS_WriteFile( checkname, buffer, 128 * 128*3 + 18 );
00580 
00581     ri.Hunk_FreeTempMemory( buffer );
00582     ri.Hunk_FreeTempMemory( source );
00583 
00584     ri.Printf( PRINT_ALL, "Wrote %s\n", checkname );
00585 }
00586 
00587 /* 
00588 ================== 
00589 R_ScreenShot_f
00590 
00591 screenshot
00592 screenshot [silent]
00593 screenshot [levelshot]
00594 screenshot [filename]
00595 
00596 Doesn't print the pacifier message if there is a second arg
00597 ================== 
00598 */  
00599 void R_ScreenShot_f (void) {
00600     char    checkname[MAX_OSPATH];
00601     static  int lastNumber = -1;
00602     qboolean    silent;
00603 
00604     if ( !strcmp( ri.Cmd_Argv(1), "levelshot" ) ) {
00605         R_LevelShot();
00606         return;
00607     }
00608 
00609     if ( !strcmp( ri.Cmd_Argv(1), "silent" ) ) {
00610         silent = qtrue;
00611     } else {
00612         silent = qfalse;
00613     }
00614 
00615     if ( ri.Cmd_Argc() == 2 && !silent ) {
00616         // explicit filename
00617         Com_sprintf( checkname, MAX_OSPATH, "screenshots/%s.tga", ri.Cmd_Argv( 1 ) );
00618     } else {
00619         // scan for a free filename
00620 
00621         // if we have saved a previous screenshot, don't scan
00622         // again, because recording demo avis can involve
00623         // thousands of shots
00624         if ( lastNumber == -1 ) {
00625             lastNumber = 0;
00626         }
00627         // scan for a free number
00628         for ( ; lastNumber <= 9999 ; lastNumber++ ) {
00629             R_ScreenshotFilename( lastNumber, checkname );
00630 
00631       if (!ri.FS_FileExists( checkname ))
00632       {
00633         break; // file doesn't exist
00634       }
00635         }
00636 
00637         if ( lastNumber >= 9999 ) {
00638             ri.Printf (PRINT_ALL, "ScreenShot: Couldn't create a file\n"); 
00639             return;
00640         }
00641 
00642         lastNumber++;
00643     }
00644 
00645     R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, qfalse );
00646 
00647     if ( !silent ) {
00648         ri.Printf (PRINT_ALL, "Wrote %s\n", checkname);
00649     }
00650 } 
00651 
00652 void R_ScreenShotJPEG_f (void) {
00653     char        checkname[MAX_OSPATH];
00654     static  int lastNumber = -1;
00655     qboolean    silent;
00656 
00657     if ( !strcmp( ri.Cmd_Argv(1), "levelshot" ) ) {
00658         R_LevelShot();
00659         return;
00660     }
00661 
00662     if ( !strcmp( ri.Cmd_Argv(1), "silent" ) ) {
00663         silent = qtrue;
00664     } else {
00665         silent = qfalse;
00666     }
00667 
00668     if ( ri.Cmd_Argc() == 2 && !silent ) {
00669         // explicit filename
00670         Com_sprintf( checkname, MAX_OSPATH, "screenshots/%s.jpg", ri.Cmd_Argv( 1 ) );
00671     } else {
00672         // scan for a free filename
00673 
00674         // if we have saved a previous screenshot, don't scan
00675         // again, because recording demo avis can involve
00676         // thousands of shots
00677         if ( lastNumber == -1 ) {
00678             lastNumber = 0;
00679         }
00680         // scan for a free number
00681         for ( ; lastNumber <= 9999 ; lastNumber++ ) {
00682             R_ScreenshotFilenameJPEG( lastNumber, checkname );
00683 
00684       if (!ri.FS_FileExists( checkname ))
00685       {
00686         break; // file doesn't exist
00687       }
00688         }
00689 
00690         if ( lastNumber == 10000 ) {
00691             ri.Printf (PRINT_ALL, "ScreenShot: Couldn't create a file\n"); 
00692             return;
00693         }
00694 
00695         lastNumber++;
00696     }
00697 
00698     R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, qtrue );
00699 
00700     if ( !silent ) {
00701         ri.Printf (PRINT_ALL, "Wrote %s\n", checkname);
00702     }
00703 } 
00704 
00705 //============================================================================
00706 
00707 /*
00708 ** GL_SetDefaultState
00709 */
00710 void GL_SetDefaultState( void )
00711 {
00712     qglClearDepth( 1.0f );
00713 
00714     qglCullFace(GL_FRONT);
00715 
00716     qglColor4f (1,1,1,1);
00717 
00718     // initialize downstream texture unit if we're running
00719     // in a multitexture environment
00720     if ( qglActiveTextureARB ) {
00721         GL_SelectTexture( 1 );
00722         GL_TextureMode( r_textureMode->string );
00723         GL_TexEnv( GL_MODULATE );
00724         qglDisable( GL_TEXTURE_2D );
00725         GL_SelectTexture( 0 );
00726     }
00727 
00728     qglEnable(GL_TEXTURE_2D);
00729     GL_TextureMode( r_textureMode->string );
00730     GL_TexEnv( GL_MODULATE );
00731 
00732     qglShadeModel( GL_SMOOTH );
00733     qglDepthFunc( GL_LEQUAL );
00734 
00735     // the vertex array is always enabled, but the color and texture
00736     // arrays are enabled and disabled around the compiled vertex array call
00737     qglEnableClientState (GL_VERTEX_ARRAY);
00738 
00739     //
00740     // make sure our GL state vector is set correctly
00741     //
00742     glState.glStateBits = GLS_DEPTHTEST_DISABLE | GLS_DEPTHMASK_TRUE;
00743 
00744     qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
00745     qglDepthMask( GL_TRUE );
00746     qglDisable( GL_DEPTH_TEST );
00747     qglEnable( GL_SCISSOR_TEST );
00748     qglDisable( GL_CULL_FACE );
00749     qglDisable( GL_BLEND );
00750 }
00751 
00752 
00753 /*
00754 ================
00755 GfxInfo_f
00756 ================
00757 */
00758 void GfxInfo_f( void ) 
00759 {
00760     cvar_t *sys_cpustring = ri.Cvar_Get( "sys_cpustring", "", 0 );
00761     const char *enablestrings[] =
00762     {
00763         "disabled",
00764         "enabled"
00765     };
00766     const char *fsstrings[] =
00767     {
00768         "windowed",
00769         "fullscreen"
00770     };
00771 
00772     ri.Printf( PRINT_ALL, "\nGL_VENDOR: %s\n", glConfig.vendor_string );
00773     ri.Printf( PRINT_ALL, "GL_RENDERER: %s\n", glConfig.renderer_string );
00774     ri.Printf( PRINT_ALL, "GL_VERSION: %s\n", glConfig.version_string );
00775     ri.Printf( PRINT_ALL, "GL_EXTENSIONS: %s\n", glConfig.extensions_string );
00776     ri.Printf( PRINT_ALL, "GL_MAX_TEXTURE_SIZE: %d\n", glConfig.maxTextureSize );
00777     ri.Printf( PRINT_ALL, "GL_MAX_ACTIVE_TEXTURES_ARB: %d\n", glConfig.maxActiveTextures );
00778     ri.Printf( PRINT_ALL, "\nPIXELFORMAT: color(%d-bits) Z(%d-bit) stencil(%d-bits)\n", glConfig.colorBits, glConfig.depthBits, glConfig.stencilBits );
00779     ri.Printf( PRINT_ALL, "MODE: %d, %d x %d %s hz:", r_mode->integer, glConfig.vidWidth, glConfig.vidHeight, fsstrings[r_fullscreen->integer == 1] );
00780     if ( glConfig.displayFrequency )
00781     {
00782         ri.Printf( PRINT_ALL, "%d\n", glConfig.displayFrequency );
00783     }
00784     else
00785     {
00786         ri.Printf( PRINT_ALL, "N/A\n" );
00787     }
00788     if ( glConfig.deviceSupportsGamma )
00789     {
00790         ri.Printf( PRINT_ALL, "GAMMA: hardware w/ %d overbright bits\n", tr.overbrightBits );
00791     }
00792     else
00793     {
00794         ri.Printf( PRINT_ALL, "GAMMA: software w/ %d overbright bits\n", tr.overbrightBits );
00795     }
00796     ri.Printf( PRINT_ALL, "CPU: %s\n", sys_cpustring->string );
00797 
00798     // rendering primitives
00799     {
00800         int     primitives;
00801 
00802         // default is to use triangles if compiled vertex arrays are present
00803         ri.Printf( PRINT_ALL, "rendering primitives: " );
00804         primitives = r_primitives->integer;
00805         if ( primitives == 0 ) {
00806             if ( qglLockArraysEXT ) {
00807                 primitives = 2;
00808             } else {
00809                 primitives = 1;
00810             }
00811         }
00812         if ( primitives == -1 ) {
00813             ri.Printf( PRINT_ALL, "none\n" );
00814         } else if ( primitives == 2 ) {
00815             ri.Printf( PRINT_ALL, "single glDrawElements\n" );
00816         } else if ( primitives == 1 ) {
00817             ri.Printf( PRINT_ALL, "multiple glArrayElement\n" );
00818         } else if ( primitives == 3 ) {
00819             ri.Printf( PRINT_ALL, "multiple glColor4ubv + glTexCoord2fv + glVertex3fv\n" );
00820         }
00821     }
00822 
00823     ri.Printf( PRINT_ALL, "texturemode: %s\n", r_textureMode->string );
00824     ri.Printf( PRINT_ALL, "picmip: %d\n", r_picmip->integer );
00825     ri.Printf( PRINT_ALL, "texture bits: %d\n", r_texturebits->integer );
00826     ri.Printf( PRINT_ALL, "multitexture: %s\n", enablestrings[qglActiveTextureARB != 0] );
00827     ri.Printf( PRINT_ALL, "compiled vertex arrays: %s\n", enablestrings[qglLockArraysEXT != 0 ] );
00828     ri.Printf( PRINT_ALL, "texenv add: %s\n", enablestrings[glConfig.textureEnvAddAvailable != 0] );
00829     ri.Printf( PRINT_ALL, "compressed textures: %s\n", enablestrings[glConfig.textureCompression!=TC_NONE] );
00830     if ( r_vertexLight->integer || glConfig.hardwareType == GLHW_PERMEDIA2 )
00831     {
00832         ri.Printf( PRINT_ALL, "HACK: using vertex lightmap approximation\n" );
00833     }
00834     if ( glConfig.hardwareType == GLHW_RAGEPRO )
00835     {
00836         ri.Printf( PRINT_ALL, "HACK: ragePro approximations\n" );
00837     }
00838     if ( glConfig.hardwareType == GLHW_RIVA128 )
00839     {
00840         ri.Printf( PRINT_ALL, "HACK: riva128 approximations\n" );
00841     }
00842     if ( glConfig.smpActive ) {
00843         ri.Printf( PRINT_ALL, "Using dual processor acceleration\n" );
00844     }
00845     if ( r_finish->integer ) {
00846         ri.Printf( PRINT_ALL, "Forcing glFinish\n" );
00847     }
00848 }
00849 
00850 /*
00851 ===============
00852 R_Register
00853 ===============
00854 */
00855 void R_Register( void ) 
00856 {
00857     //
00858     // latched and archived variables
00859     //
00860     r_glDriver = ri.Cvar_Get( "r_glDriver", OPENGL_DRIVER_NAME, CVAR_ARCHIVE | CVAR_LATCH );
00861     r_allowExtensions = ri.Cvar_Get( "r_allowExtensions", "1", CVAR_ARCHIVE | CVAR_LATCH );
00862     r_ext_compressed_textures = ri.Cvar_Get( "r_ext_compressed_textures", "0", CVAR_ARCHIVE | CVAR_LATCH );
00863     r_ext_gamma_control = ri.Cvar_Get( "r_ext_gamma_control", "1", CVAR_ARCHIVE | CVAR_LATCH );
00864     r_ext_multitexture = ri.Cvar_Get( "r_ext_multitexture", "1", CVAR_ARCHIVE | CVAR_LATCH );
00865     r_ext_compiled_vertex_array = ri.Cvar_Get( "r_ext_compiled_vertex_array", "1", CVAR_ARCHIVE | CVAR_LATCH);
00866 #ifdef __linux__ // broken on linux
00867     r_ext_texture_env_add = ri.Cvar_Get( "r_ext_texture_env_add", "0", CVAR_ARCHIVE | CVAR_LATCH);
00868 #else
00869     r_ext_texture_env_add = ri.Cvar_Get( "r_ext_texture_env_add", "1", CVAR_ARCHIVE | CVAR_LATCH);
00870 #endif
00871 
00872     r_picmip = ri.Cvar_Get ("r_picmip", "1", CVAR_ARCHIVE | CVAR_LATCH );
00873     r_roundImagesDown = ri.Cvar_Get ("r_roundImagesDown", "1", CVAR_ARCHIVE | CVAR_LATCH );
00874     r_colorMipLevels = ri.Cvar_Get ("r_colorMipLevels", "0", CVAR_LATCH );
00875     AssertCvarRange( r_picmip, 0, 16, qtrue );
00876     r_detailTextures = ri.Cvar_Get( "r_detailtextures", "1", CVAR_ARCHIVE | CVAR_LATCH );
00877     r_texturebits = ri.Cvar_Get( "r_texturebits", "0", CVAR_ARCHIVE | CVAR_LATCH );
00878     r_colorbits = ri.Cvar_Get( "r_colorbits", "0", CVAR_ARCHIVE | CVAR_LATCH );
00879     r_stereo = ri.Cvar_Get( "r_stereo", "0", CVAR_ARCHIVE | CVAR_LATCH );
00880 #ifdef __linux__
00881     r_stencilbits = ri.Cvar_Get( "r_stencilbits", "0", CVAR_ARCHIVE | CVAR_LATCH );
00882 #else
00883     r_stencilbits = ri.Cvar_Get( "r_stencilbits", "8", CVAR_ARCHIVE | CVAR_LATCH );
00884 #endif
00885     r_depthbits = ri.Cvar_Get( "r_depthbits", "0", CVAR_ARCHIVE | CVAR_LATCH );
00886     r_overBrightBits = ri.Cvar_Get ("r_overBrightBits", "1", CVAR_ARCHIVE | CVAR_LATCH );
00887     r_ignorehwgamma = ri.Cvar_Get( "r_ignorehwgamma", "0", CVAR_ARCHIVE | CVAR_LATCH);
00888     r_mode = ri.Cvar_Get( "r_mode", "3", CVAR_ARCHIVE | CVAR_LATCH );
00889     r_fullscreen = ri.Cvar_Get( "r_fullscreen", "1", CVAR_ARCHIVE | CVAR_LATCH );
00890     r_customwidth = ri.Cvar_Get( "r_customwidth", "1600", CVAR_ARCHIVE | CVAR_LATCH );
00891     r_customheight = ri.Cvar_Get( "r_customheight", "1024", CVAR_ARCHIVE | CVAR_LATCH );
00892     r_customaspect = ri.Cvar_Get( "r_customaspect", "1", CVAR_ARCHIVE | CVAR_LATCH );
00893     r_simpleMipMaps = ri.Cvar_Get( "r_simpleMipMaps", "1", CVAR_ARCHIVE | CVAR_LATCH );
00894     r_vertexLight = ri.Cvar_Get( "r_vertexLight", "0", CVAR_ARCHIVE | CVAR_LATCH );
00895     r_uiFullScreen = ri.Cvar_Get( "r_uifullscreen", "0", 0);
00896     r_subdivisions = ri.Cvar_Get ("r_subdivisions", "4", CVAR_ARCHIVE | CVAR_LATCH);
00897 #if (defined(MACOS_X) || defined(__linux__)) && defined(SMP)
00898   // Default to using SMP on Mac OS X or Linux if we have multiple processors
00899     r_smp = ri.Cvar_Get( "r_smp", Sys_ProcessorCount() > 1 ? "1" : "0", CVAR_ARCHIVE | CVAR_LATCH);
00900 #else        
00901     r_smp = ri.Cvar_Get( "r_smp", "0", CVAR_ARCHIVE | CVAR_LATCH);
00902 #endif
00903     r_ignoreFastPath = ri.Cvar_Get( "r_ignoreFastPath", "1", CVAR_ARCHIVE | CVAR_LATCH );
00904 
00905     //
00906     // temporary latched variables that can only change over a restart
00907     //
00908     r_displayRefresh = ri.Cvar_Get( "r_displayRefresh", "0", CVAR_LATCH );
00909     AssertCvarRange( r_displayRefresh, 0, 200, qtrue );
00910     r_fullbright = ri.Cvar_Get ("r_fullbright", "0", CVAR_LATCH|CVAR_CHEAT );
00911     r_mapOverBrightBits = ri.Cvar_Get ("r_mapOverBrightBits", "2", CVAR_LATCH );
00912     r_intensity = ri.Cvar_Get ("r_intensity", "1", CVAR_LATCH );
00913     r_singleShader = ri.Cvar_Get ("r_singleShader", "0", CVAR_CHEAT | CVAR_LATCH );
00914 
00915     //
00916     // archived variables that can change at any time
00917     //
00918     r_lodCurveError = ri.Cvar_Get( "r_lodCurveError", "250", CVAR_ARCHIVE|CVAR_CHEAT );
00919     r_lodbias = ri.Cvar_Get( "r_lodbias", "0", CVAR_ARCHIVE );
00920     r_flares = ri.Cvar_Get ("r_flares", "0", CVAR_ARCHIVE );
00921     r_znear = ri.Cvar_Get( "r_znear", "4", CVAR_CHEAT );
00922     AssertCvarRange( r_znear, 0.001f, 200, qtrue );
00923     r_ignoreGLErrors = ri.Cvar_Get( "r_ignoreGLErrors", "1", CVAR_ARCHIVE );
00924     r_fastsky = ri.Cvar_Get( "r_fastsky", "0", CVAR_ARCHIVE );
00925     r_inGameVideo = ri.Cvar_Get( "r_inGameVideo", "1", CVAR_ARCHIVE );
00926     r_drawSun = ri.Cvar_Get( "r_drawSun", "0", CVAR_ARCHIVE );
00927     r_dynamiclight = ri.Cvar_Get( "r_dynamiclight", "1", CVAR_ARCHIVE );
00928     r_dlightBacks = ri.Cvar_Get( "r_dlightBacks", "1", CVAR_ARCHIVE );
00929     r_finish = ri.Cvar_Get ("r_finish", "0", CVAR_ARCHIVE);
00930     r_textureMode = ri.Cvar_Get( "r_textureMode", "GL_LINEAR_MIPMAP_NEAREST", CVAR_ARCHIVE );
00931     r_swapInterval = ri.Cvar_Get( "r_swapInterval", "0", CVAR_ARCHIVE );
00932 #ifdef __MACOS__
00933     r_gamma = ri.Cvar_Get( "r_gamma", "1.2", CVAR_ARCHIVE );
00934 #else
00935     r_gamma = ri.Cvar_Get( "r_gamma", "1", CVAR_ARCHIVE );
00936 #endif
00937     r_facePlaneCull = ri.Cvar_Get ("r_facePlaneCull", "1", CVAR_ARCHIVE );
00938 
00939     r_railWidth = ri.Cvar_Get( "r_railWidth", "16", CVAR_ARCHIVE );
00940     r_railCoreWidth = ri.Cvar_Get( "r_railCoreWidth", "6", CVAR_ARCHIVE );
00941     r_railSegmentLength = ri.Cvar_Get( "r_railSegmentLength", "32", CVAR_ARCHIVE );
00942 
00943     r_primitives = ri.Cvar_Get( "r_primitives", "0", CVAR_ARCHIVE );
00944 
00945     r_ambientScale = ri.Cvar_Get( "r_ambientScale", "0.6", CVAR_CHEAT );
00946     r_directedScale = ri.Cvar_Get( "r_directedScale", "1", CVAR_CHEAT );
00947 
00948     //
00949     // temporary variables that can change at any time
00950     //
00951     r_showImages = ri.Cvar_Get( "r_showImages", "0", CVAR_TEMP );
00952 
00953     r_debugLight = ri.Cvar_Get( "r_debuglight", "0", CVAR_TEMP );
00954     r_debugSort = ri.Cvar_Get( "r_debugSort", "0", CVAR_CHEAT );
00955     r_printShaders = ri.Cvar_Get( "r_printShaders", "0", 0 );
00956     r_saveFontData = ri.Cvar_Get( "r_saveFontData", "0", 0 );
00957 
00958     r_nocurves = ri.Cvar_Get ("r_nocurves", "0", CVAR_CHEAT );
00959     r_drawworld = ri.Cvar_Get ("r_drawworld", "1", CVAR_CHEAT );
00960     r_lightmap = ri.Cvar_Get ("r_lightmap", "0", 0 );
00961     r_portalOnly = ri.Cvar_Get ("r_portalOnly", "0", CVAR_CHEAT );
00962 
00963     r_flareSize = ri.Cvar_Get ("r_flareSize", "40", CVAR_CHEAT);
00964     r_flareFade = ri.Cvar_Get ("r_flareFade", "7", CVAR_CHEAT);
00965 
00966     r_showSmp = ri.Cvar_Get ("r_showSmp", "0", CVAR_CHEAT);
00967     r_skipBackEnd = ri.Cvar_Get ("r_skipBackEnd", "0", CVAR_CHEAT);
00968 
00969     r_measureOverdraw = ri.Cvar_Get( "r_measureOverdraw", "0", CVAR_CHEAT );
00970     r_lodscale = ri.Cvar_Get( "r_lodscale", "5", CVAR_CHEAT );
00971     r_norefresh = ri.Cvar_Get ("r_norefresh", "0", CVAR_CHEAT);
00972     r_drawentities = ri.Cvar_Get ("r_drawentities", "1", CVAR_CHEAT );
00973     r_ignore = ri.Cvar_Get( "r_ignore", "1", CVAR_CHEAT );
00974     r_nocull = ri.Cvar_Get ("r_nocull", "0", CVAR_CHEAT);
00975     r_novis = ri.Cvar_Get ("r_novis", "0", CVAR_CHEAT);
00976     r_showcluster = ri.Cvar_Get ("r_showcluster", "0", CVAR_CHEAT);
00977     r_speeds = ri.Cvar_Get ("r_speeds", "0", CVAR_CHEAT);
00978     r_verbose = ri.Cvar_Get( "r_verbose", "0", CVAR_CHEAT );
00979     r_logFile = ri.Cvar_Get( "r_logFile", "0", CVAR_CHEAT );
00980     r_debugSurface = ri.Cvar_Get ("r_debugSurface", "0", CVAR_CHEAT);
00981     r_nobind = ri.Cvar_Get ("r_nobind", "0", CVAR_CHEAT);
00982     r_showtris = ri.Cvar_Get ("r_showtris", "0", CVAR_CHEAT);
00983     r_showsky = ri.Cvar_Get ("r_showsky", "0", CVAR_CHEAT);
00984     r_shownormals = ri.Cvar_Get ("r_shownormals", "0", CVAR_CHEAT);
00985     r_clear = ri.Cvar_Get ("r_clear", "0", CVAR_CHEAT);
00986     r_offsetFactor = ri.Cvar_Get( "r_offsetfactor", "-1", CVAR_CHEAT );
00987     r_offsetUnits = ri.Cvar_Get( "r_offsetunits", "-2", CVAR_CHEAT );
00988     r_drawBuffer = ri.Cvar_Get( "r_drawBuffer", "GL_BACK", CVAR_CHEAT );
00989     r_lockpvs = ri.Cvar_Get ("r_lockpvs", "0", CVAR_CHEAT);
00990     r_noportals = ri.Cvar_Get ("r_noportals", "0", CVAR_CHEAT);
00991     r_shadows = ri.Cvar_Get( "cg_shadows", "1", 0 );
00992 
00993     r_maxpolys = ri.Cvar_Get( "r_maxpolys", va("%d", MAX_POLYS), 0);
00994     r_maxpolyverts = ri.Cvar_Get( "r_maxpolyverts", va("%d", MAX_POLYVERTS), 0);
00995 
00996     // make sure all the commands added here are also
00997     // removed in R_Shutdown
00998     ri.Cmd_AddCommand( "imagelist", R_ImageList_f );
00999     ri.Cmd_AddCommand( "shaderlist", R_ShaderList_f );
01000     ri.Cmd_AddCommand( "skinlist", R_SkinList_f );
01001     ri.Cmd_AddCommand( "modellist", R_Modellist_f );
01002     ri.Cmd_AddCommand( "modelist", R_ModeList_f );
01003