summaryrefslogtreecommitdiff
path: root/src/renderer/tr_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/renderer/tr_init.c')
-rw-r--r--src/renderer/tr_init.c1358
1 files changed, 1358 insertions, 0 deletions
diff --git a/src/renderer/tr_init.c b/src/renderer/tr_init.c
new file mode 100644
index 0000000..10ea222
--- /dev/null
+++ b/src/renderer/tr_init.c
@@ -0,0 +1,1358 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+Copyright (C) 2000-2009 Darklegion Development
+
+This file is part of Tremulous.
+
+Tremulous is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Tremulous is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Tremulous; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// tr_init.c -- functions that are not called every frame
+
+#include "tr_local.h"
+
+glconfig_t glConfig;
+glstate_t glState;
+
+static void GfxInfo_f( void );
+
+cvar_t *r_flareSize;
+cvar_t *r_flareFade;
+cvar_t *r_flareCoeff;
+
+cvar_t *r_railWidth;
+cvar_t *r_railCoreWidth;
+cvar_t *r_railSegmentLength;
+
+cvar_t *r_ignoreFastPath;
+
+cvar_t *r_verbose;
+cvar_t *r_ignore;
+
+cvar_t *r_detailTextures;
+
+cvar_t *r_znear;
+cvar_t *r_zproj;
+cvar_t *r_stereoSeparation;
+
+cvar_t *r_smp;
+cvar_t *r_showSmp;
+cvar_t *r_skipBackEnd;
+
+cvar_t *r_stereoEnabled;
+cvar_t *r_anaglyphMode;
+
+cvar_t *r_greyscale;
+
+cvar_t *r_ignorehwgamma;
+cvar_t *r_measureOverdraw;
+
+cvar_t *r_inGameVideo;
+cvar_t *r_fastsky;
+cvar_t *r_drawSun;
+cvar_t *r_dynamiclight;
+cvar_t *r_dlightBacks;
+
+cvar_t *r_lodbias;
+cvar_t *r_lodscale;
+
+cvar_t *r_norefresh;
+cvar_t *r_drawentities;
+cvar_t *r_drawworld;
+cvar_t *r_speeds;
+cvar_t *r_fullbright;
+cvar_t *r_novis;
+cvar_t *r_nocull;
+cvar_t *r_facePlaneCull;
+cvar_t *r_showcluster;
+cvar_t *r_nocurves;
+
+cvar_t *r_allowExtensions;
+
+cvar_t *r_ext_compressed_textures;
+cvar_t *r_ext_multitexture;
+cvar_t *r_ext_compiled_vertex_array;
+cvar_t *r_ext_texture_env_add;
+cvar_t *r_ext_texture_filter_anisotropic;
+cvar_t *r_ext_max_anisotropy;
+
+cvar_t *r_ignoreGLErrors;
+cvar_t *r_logFile;
+
+cvar_t *r_stencilbits;
+cvar_t *r_depthbits;
+cvar_t *r_colorbits;
+cvar_t *r_primitives;
+cvar_t *r_texturebits;
+cvar_t *r_ext_multisample;
+
+cvar_t *r_drawBuffer;
+cvar_t *r_lightmap;
+cvar_t *r_vertexLight;
+cvar_t *r_uiFullScreen;
+cvar_t *r_shadows;
+cvar_t *r_flares;
+cvar_t *r_nobind;
+cvar_t *r_singleShader;
+cvar_t *r_roundImagesDown;
+cvar_t *r_colorMipLevels;
+cvar_t *r_picmip;
+cvar_t *r_showtris;
+cvar_t *r_showsky;
+cvar_t *r_shownormals;
+cvar_t *r_finish;
+cvar_t *r_clear;
+cvar_t *r_swapInterval;
+cvar_t *r_textureMode;
+cvar_t *r_offsetFactor;
+cvar_t *r_offsetUnits;
+cvar_t *r_gamma;
+cvar_t *r_intensity;
+cvar_t *r_lockpvs;
+cvar_t *r_noportals;
+cvar_t *r_portalOnly;
+
+cvar_t *r_subdivisions;
+cvar_t *r_lodCurveError;
+
+cvar_t *r_fullscreen;
+cvar_t *r_noborder;
+
+cvar_t *r_width;
+cvar_t *r_height;
+cvar_t *r_pixelAspect;
+
+cvar_t *r_overBrightBits;
+cvar_t *r_mapOverBrightBits;
+
+cvar_t *r_debugSurface;
+cvar_t *r_simpleMipMaps;
+
+cvar_t *r_showImages;
+
+cvar_t *r_ambientScale;
+cvar_t *r_directedScale;
+cvar_t *r_debugLight;
+cvar_t *r_debugSort;
+cvar_t *r_printShaders;
+cvar_t *r_saveFontData;
+
+cvar_t *r_marksOnTriangleMeshes;
+
+cvar_t *r_aviMotionJpegQuality;
+cvar_t *r_screenshotJpegQuality;
+
+cvar_t *r_maxpolys;
+int max_polys;
+cvar_t *r_maxpolyverts;
+int max_polyverts;
+
+#define GENERIC_HW_R_PICMIP_DEFAULT "0"
+#define GENERIC_HW_R_TEXTUREMODE_DEFAULT "GL_LINEAR_MIPMAP_LINEAR"
+
+/*
+==================
+GL_ResolveHardwareType
+
+Chipset specific configuration
+==================
+*/
+void GL_ResolveHardwareType( void )
+{
+ char buf[ 1024 ];
+ cvar_t *lastValidRenderer = ri.Cvar_Get(
+ "r_lastValidRenderer", "(uninitialized)", CVAR_ARCHIVE );
+
+ Q_strncpyz( buf, glConfig.renderer_string, sizeof( buf ) );
+ Q_strlwr( buf );
+
+ // NOTE: if changing cvars, do it within this block. This allows them
+ // to be overridden when testing driver fixes, etc. but only sets
+ // them to their default state when the hardware is first installed/run.
+ if( Q_stricmp( lastValidRenderer->string, glConfig.renderer_string ) )
+ {
+ glConfig.hardwareType = GLHW_GENERIC;
+
+ ri.Cvar_Set( "r_textureMode", GENERIC_HW_R_TEXTUREMODE_DEFAULT );
+
+ // VOODOO GRAPHICS w/ 2MB
+ if ( strstr( buf, "voodoo graphics/1 tmu/2 mb" ) )
+ {
+ ri.Cvar_Set( "r_picmip", "2" );
+ ri.Cvar_Get( "r_picmip", "1", CVAR_ARCHIVE | CVAR_LATCH );
+ }
+ else
+ {
+ ri.Cvar_Set( "r_picmip", GENERIC_HW_R_PICMIP_DEFAULT );
+
+ if ( strstr( buf, "rage 128" ) || strstr( buf, "rage128" ) )
+ {
+ ri.Cvar_Set( "r_finish", "0" );
+ }
+ // Savage3D and Savage4 should always have trilinear enabled
+ else if ( strstr( buf, "savage3d" ) || strstr( buf, "s3 savage4" ) )
+ {
+ ri.Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_LINEAR" );
+ }
+ }
+ }
+
+ //
+ // this is where hardware specific workarounds that should be
+ // detected/initialized every startup should go.
+ //
+ if ( strstr( buf, "banshee" ) || strstr( buf, "voodoo3" ) )
+ {
+ glConfig.hardwareType = GLHW_3DFX_2D3D;
+ }
+ // VOODOO GRAPHICS w/ 2MB
+ else if ( strstr( buf, "voodoo graphics/1 tmu/2 mb" ) )
+ {
+ }
+ else if ( strstr( buf, "glzicd" ) )
+ {
+ }
+ else if ( strstr( buf, "rage pro" ) ||
+ strstr( buf, "Rage Pro" ) ||
+ strstr( buf, "ragepro" ) )
+ {
+ glConfig.hardwareType = GLHW_RAGEPRO;
+ }
+ else if ( strstr( buf, "rage 128" ) )
+ {
+ }
+ else if ( strstr( buf, "permedia2" ) )
+ {
+ glConfig.hardwareType = GLHW_PERMEDIA2;
+ }
+ else if ( strstr( buf, "riva 128" ) )
+ {
+ glConfig.hardwareType = GLHW_RIVA128;
+ }
+ else if ( strstr( buf, "riva tnt " ) )
+ {
+ }
+}
+
+/*
+** InitOpenGL
+**
+** This function is responsible for initializing a valid OpenGL subsystem. This
+** is done by calling GLimp_Init (which gives us a working OGL subsystem) then
+** setting variables, checking GL constants, and reporting the gfx system config
+** to the user.
+*/
+static void InitOpenGL( void )
+{
+ char renderer_buffer[1024];
+
+ //
+ // initialize OS specific portions of the renderer
+ //
+ // GLimp_Init directly or indirectly references the following cvars:
+ // - r_fullscreen
+ // - r_(width|height|pixelAspect)
+ // - r_(color|depth|stencil)bits
+ // - r_ignorehwgamma
+ // - r_gamma
+ //
+
+ if ( glConfig.vidWidth == 0 )
+ {
+ GLint temp;
+
+ GLimp_Init();
+
+ strcpy( renderer_buffer, glConfig.renderer_string );
+ Q_strlwr( renderer_buffer );
+
+ // OpenGL driver constants
+ qglGetIntegerv( GL_MAX_TEXTURE_SIZE, &temp );
+ glConfig.maxTextureSize = temp;
+
+ // stubbed or broken drivers may have reported 0...
+ if ( glConfig.maxTextureSize <= 0 )
+ {
+ glConfig.maxTextureSize = 0;
+ }
+ }
+
+ // init command buffers and SMP
+ R_InitCommandBuffers();
+
+ // print info
+ GfxInfo_f();
+
+ // set default state
+ GL_SetDefaultState();
+}
+
+/*
+==================
+GL_CheckErrors
+==================
+*/
+void GL_CheckErrors( void ) {
+ int err;
+ char s[64];
+
+ err = qglGetError();
+ if ( err == GL_NO_ERROR ) {
+ return;
+ }
+ if ( r_ignoreGLErrors->integer ) {
+ return;
+ }
+ switch( err ) {
+ case GL_INVALID_ENUM:
+ strcpy( s, "GL_INVALID_ENUM" );
+ break;
+ case GL_INVALID_VALUE:
+ strcpy( s, "GL_INVALID_VALUE" );
+ break;
+ case GL_INVALID_OPERATION:
+ strcpy( s, "GL_INVALID_OPERATION" );
+ break;
+ case GL_STACK_OVERFLOW:
+ strcpy( s, "GL_STACK_OVERFLOW" );
+ break;
+ case GL_STACK_UNDERFLOW:
+ strcpy( s, "GL_STACK_UNDERFLOW" );
+ break;
+ case GL_OUT_OF_MEMORY:
+ strcpy( s, "GL_OUT_OF_MEMORY" );
+ break;
+ default:
+ Com_sprintf( s, sizeof(s), "%i", err);
+ break;
+ }
+
+ ri.Error( ERR_FATAL, "GL_CheckErrors: %s", s );
+}
+
+
+/*
+==============================================================================
+
+ SCREEN SHOTS
+
+NOTE TTimo
+some thoughts about the screenshots system:
+screenshots get written in fs_homepath + fs_gamedir
+vanilla q3 .. baseq3/screenshots/ *.tga
+team arena .. missionpack/screenshots/ *.tga
+
+two commands: "screenshot" and "screenshotJPEG"
+we use statics to store a count and start writing the first screenshot/screenshot????.tga (.jpg) available
+(with FS_FileExists / FS_FOpenFileWrite calls)
+FIXME: the statics don't get a reinit between fs_game changes
+
+==============================================================================
+*/
+
+/*
+==================
+RB_ReadPixels
+
+Reads an image but takes care of alignment issues for reading RGB images.
+
+Reads a minimum offset for where the RGB data starts in the image from
+integer stored at pointer offset. When the function has returned the actual
+offset was written back to address offset. This address will always have an
+alignment of packAlign to ensure efficient copying.
+
+Stores the length of padding after a line of pixels to address padlen
+
+Return value must be freed with ri.Hunk_FreeTempMemory()
+==================
+*/
+
+byte *RB_ReadPixels(int x, int y, int width, int height, size_t *offset, int *padlen)
+{
+ byte *buffer, *bufstart;
+ int padwidth, linelen;
+ GLint packAlign;
+
+ qglGetIntegerv(GL_PACK_ALIGNMENT, &packAlign);
+
+ linelen = width * 3;
+ padwidth = PAD(linelen, packAlign);
+
+ // Allocate a few more bytes so that we can choose an alignment we like
+ buffer = ri.Hunk_AllocateTempMemory(padwidth * height + *offset + packAlign - 1);
+
+ bufstart = (byte *) PAD((intptr_t) buffer + *offset, packAlign);
+ qglReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, bufstart);
+
+ *offset = bufstart - buffer;
+ *padlen = padwidth - linelen;
+
+ return buffer;
+}
+
+/*
+==================
+RB_TakeScreenshot
+==================
+*/
+void RB_TakeScreenshot(int x, int y, int width, int height, char *fileName)
+{
+ byte *allbuf, *buffer;
+ byte *srcptr, *destptr;
+ byte *endline, *endmem;
+ byte temp;
+
+ int linelen, padlen;
+ size_t offset = 18, memcount;
+
+ allbuf = RB_ReadPixels(x, y, width, height, &offset, &padlen);
+ buffer = allbuf + offset - 18;
+
+ Com_Memset (buffer, 0, 18);
+ buffer[2] = 2; // uncompressed type
+ buffer[12] = width & 255;
+ buffer[13] = width >> 8;
+ buffer[14] = height & 255;
+ buffer[15] = height >> 8;
+ buffer[16] = 24; // pixel size
+
+ // swap rgb to bgr and remove padding from line endings
+ linelen = width * 3;
+
+ srcptr = destptr = allbuf + offset;
+ endmem = srcptr + (linelen + padlen) * height;
+
+ while(srcptr < endmem)
+ {
+ endline = srcptr + linelen;
+
+ while(srcptr < endline)
+ {
+ temp = srcptr[0];
+ *destptr++ = srcptr[2];
+ *destptr++ = srcptr[1];
+ *destptr++ = temp;
+
+ srcptr += 3;
+ }
+
+ // Skip the pad
+ srcptr += padlen;
+ }
+
+ memcount = linelen * height;
+
+ // gamma correct
+ if(glConfig.deviceSupportsGamma)
+ R_GammaCorrect(allbuf + offset, memcount);
+
+ ri.FS_WriteFile(fileName, buffer, memcount + 18);
+
+ ri.Hunk_FreeTempMemory(allbuf);
+}
+
+/*
+==================
+RB_TakeScreenshotJPEG
+==================
+*/
+
+void RB_TakeScreenshotJPEG(int x, int y, int width, int height, char *fileName)
+{
+ byte *buffer;
+ size_t offset = 0, memcount;
+ int padlen;
+
+ buffer = RB_ReadPixels(x, y, width, height, &offset, &padlen);
+ memcount = (width * 3 + padlen) * height;
+
+ // gamma correct
+ if(glConfig.deviceSupportsGamma)
+ R_GammaCorrect(buffer + offset, memcount);
+
+ RE_SaveJPG(fileName, r_screenshotJpegQuality->integer, width, height, buffer + offset, padlen);
+ ri.Hunk_FreeTempMemory(buffer);
+}
+
+/*
+==================
+RB_TakeScreenshotCmd
+==================
+*/
+const void *RB_TakeScreenshotCmd( const void *data ) {
+ const screenshotCommand_t *cmd;
+
+ cmd = (const screenshotCommand_t *)data;
+
+ if (cmd->jpeg)
+ RB_TakeScreenshotJPEG( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName);
+ else
+ RB_TakeScreenshot( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName);
+
+ return (const void *)(cmd + 1);
+}
+
+/*
+==================
+R_TakeScreenshot
+==================
+*/
+void R_TakeScreenshot( int x, int y, int width, int height, char *name, qboolean jpeg ) {
+ static char fileName[MAX_OSPATH]; // bad things if two screenshots per frame?
+ screenshotCommand_t *cmd;
+
+ cmd = R_GetCommandBuffer( sizeof( *cmd ) );
+ if ( !cmd ) {
+ return;
+ }
+ cmd->commandId = RC_SCREENSHOT;
+
+ cmd->x = x;
+ cmd->y = y;
+ cmd->width = width;
+ cmd->height = height;
+ Q_strncpyz( fileName, name, sizeof(fileName) );
+ cmd->fileName = fileName;
+ cmd->jpeg = jpeg;
+}
+
+/*
+==================
+R_ScreenshotFilename
+==================
+*/
+void R_ScreenshotFilename( int lastNumber, char *fileName ) {
+ int a,b,c,d;
+
+ if ( lastNumber < 0 || lastNumber > 9999 ) {
+ Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot9999.tga" );
+ return;
+ }
+
+ a = lastNumber / 1000;
+ lastNumber -= a*1000;
+ b = lastNumber / 100;
+ lastNumber -= b*100;
+ c = lastNumber / 10;
+ lastNumber -= c*10;
+ d = lastNumber;
+
+ Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot%i%i%i%i.tga"
+ , a, b, c, d );
+}
+
+/*
+==================
+R_ScreenshotFilename
+==================
+*/
+void R_ScreenshotFilenameJPEG( int lastNumber, char *fileName ) {
+ int a,b,c,d;
+
+ if ( lastNumber < 0 || lastNumber > 9999 ) {
+ Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot9999.jpg" );
+ return;
+ }
+
+ a = lastNumber / 1000;
+ lastNumber -= a*1000;
+ b = lastNumber / 100;
+ lastNumber -= b*100;
+ c = lastNumber / 10;
+ lastNumber -= c*10;
+ d = lastNumber;
+
+ Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot%i%i%i%i.jpg"
+ , a, b, c, d );
+}
+
+/*
+====================
+R_LevelShot
+
+levelshots are specialized 128*128 thumbnails for
+the menu system, sampled down from full screen distorted images
+====================
+*/
+void R_LevelShot( void ) {
+ char checkname[MAX_OSPATH];
+ byte *buffer;
+ byte *source, *allsource;
+ byte *src, *dst;
+ size_t offset = 0;
+ int padlen;
+ int x, y;
+ int r, g, b;
+ float xScale, yScale;
+ int xx, yy;
+
+ Com_sprintf(checkname, sizeof(checkname), "levelshots/%s.tga", tr.world->baseName);
+
+ allsource = RB_ReadPixels(0, 0, glConfig.vidWidth, glConfig.vidHeight, &offset, &padlen);
+ source = allsource + offset;
+
+ buffer = ri.Hunk_AllocateTempMemory(128 * 128*3 + 18);
+ Com_Memset (buffer, 0, 18);
+ buffer[2] = 2; // uncompressed type
+ buffer[12] = 128;
+ buffer[14] = 128;
+ buffer[16] = 24; // pixel size
+
+ // resample from source
+ xScale = glConfig.vidWidth / 512.0f;
+ yScale = glConfig.vidHeight / 384.0f;
+ for ( y = 0 ; y < 128 ; y++ ) {
+ for ( x = 0 ; x < 128 ; x++ ) {
+ r = g = b = 0;
+ for ( yy = 0 ; yy < 3 ; yy++ ) {
+ for ( xx = 0 ; xx < 4 ; xx++ ) {
+ src = source + (3 * glConfig.vidWidth + padlen) * (int)((y*3 + yy) * yScale) +
+ 3 * (int) ((x*4 + xx) * xScale);
+ r += src[0];
+ g += src[1];
+ b += src[2];
+ }
+ }
+ dst = buffer + 18 + 3 * ( y * 128 + x );
+ dst[0] = b / 12;
+ dst[1] = g / 12;
+ dst[2] = r / 12;
+ }
+ }
+
+ // gamma correct
+ if ( glConfig.deviceSupportsGamma ) {
+ R_GammaCorrect( buffer + 18, 128 * 128 * 3 );
+ }
+
+ ri.FS_WriteFile( checkname, buffer, 128 * 128*3 + 18 );
+
+ ri.Hunk_FreeTempMemory(buffer);
+ ri.Hunk_FreeTempMemory(allsource);
+
+ ri.Printf( PRINT_ALL, "Wrote %s\n", checkname );
+}
+
+/*
+==================
+R_ScreenShot_f
+
+screenshot
+screenshot [silent]
+screenshot [levelshot]
+screenshot [filename]
+
+Doesn't print the pacifier message if there is a second arg
+==================
+*/
+void R_ScreenShot_f (void) {
+ char checkname[MAX_OSPATH];
+ static int lastNumber = -1;
+ qboolean silent;
+
+ if ( !strcmp( ri.Cmd_Argv(1), "levelshot" ) ) {
+ R_LevelShot();
+ return;
+ }
+
+ if ( !strcmp( ri.Cmd_Argv(1), "silent" ) ) {
+ silent = qtrue;
+ } else {
+ silent = qfalse;
+ }
+
+ if ( ri.Cmd_Argc() == 2 && !silent ) {
+ // explicit filename
+ Com_sprintf( checkname, MAX_OSPATH, "screenshots/%s.tga", ri.Cmd_Argv( 1 ) );
+ } else {
+ // scan for a free filename
+
+ // if we have saved a previous screenshot, don't scan
+ // again, because recording demo avis can involve
+ // thousands of shots
+ if ( lastNumber == -1 ) {
+ lastNumber = 0;
+ }
+ // scan for a free number
+ for ( ; lastNumber <= 9999 ; lastNumber++ ) {
+ R_ScreenshotFilename( lastNumber, checkname );
+
+ if (!ri.FS_FileExists( checkname ))
+ {
+ break; // file doesn't exist
+ }
+ }
+
+ if ( lastNumber >= 9999 ) {
+ ri.Printf (PRINT_ALL, "ScreenShot: Couldn't create a file\n");
+ return;
+ }
+
+ lastNumber++;
+ }
+
+ R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, qfalse );
+
+ if ( !silent ) {
+ ri.Printf (PRINT_ALL, "Wrote %s\n", checkname);
+ }
+}
+
+void R_ScreenShotJPEG_f (void) {
+ char checkname[MAX_OSPATH];
+ static int lastNumber = -1;
+ qboolean silent;
+
+ if ( !strcmp( ri.Cmd_Argv(1), "levelshot" ) ) {
+ R_LevelShot();
+ return;
+ }
+
+ if ( !strcmp( ri.Cmd_Argv(1), "silent" ) ) {
+ silent = qtrue;
+ } else {
+ silent = qfalse;
+ }
+
+ if ( ri.Cmd_Argc() == 2 && !silent ) {
+ // explicit filename
+ Com_sprintf( checkname, MAX_OSPATH, "screenshots/%s.jpg", ri.Cmd_Argv( 1 ) );
+ } else {
+ // scan for a free filename
+
+ // if we have saved a previous screenshot, don't scan
+ // again, because recording demo avis can involve
+ // thousands of shots
+ if ( lastNumber == -1 ) {
+ lastNumber = 0;
+ }
+ // scan for a free number
+ for ( ; lastNumber <= 9999 ; lastNumber++ ) {
+ R_ScreenshotFilenameJPEG( lastNumber, checkname );
+
+ if (!ri.FS_FileExists( checkname ))
+ {
+ break; // file doesn't exist
+ }
+ }
+
+ if ( lastNumber == 10000 ) {
+ ri.Printf (PRINT_ALL, "ScreenShot: Couldn't create a file\n");
+ return;
+ }
+
+ lastNumber++;
+ }
+
+ R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, qtrue );
+
+ if ( !silent ) {
+ ri.Printf (PRINT_ALL, "Wrote %s\n", checkname);
+ }
+}
+
+//============================================================================
+
+/*
+==================
+RB_TakeVideoFrameCmd
+==================
+*/
+const void *RB_TakeVideoFrameCmd( const void *data )
+{
+ const videoFrameCommand_t *cmd;
+ byte *cBuf;
+ size_t memcount, linelen;
+ int padwidth, avipadwidth, padlen, avipadlen;
+ GLint packAlign;
+
+ cmd = (const videoFrameCommand_t *)data;
+
+ qglGetIntegerv(GL_PACK_ALIGNMENT, &packAlign);
+
+ linelen = cmd->width * 3;
+
+ // Alignment stuff for glReadPixels
+ padwidth = PAD(linelen, packAlign);
+ padlen = padwidth - linelen;
+ // AVI line padding
+ avipadwidth = PAD(linelen, AVI_LINE_PADDING);
+ avipadlen = avipadwidth - linelen;
+
+ cBuf = (byte *) PAD((intptr_t) cmd->captureBuffer, packAlign);
+
+ qglReadPixels(0, 0, cmd->width, cmd->height, GL_RGB,
+ GL_UNSIGNED_BYTE, cBuf);
+
+ memcount = padwidth * cmd->height;
+
+ // gamma correct
+ if(glConfig.deviceSupportsGamma)
+ R_GammaCorrect(cBuf, memcount);
+
+ if(cmd->motionJpeg)
+ {
+ memcount = RE_SaveJPGToBuffer(cmd->encodeBuffer, linelen * cmd->height,
+ r_aviMotionJpegQuality->integer,
+ cmd->width, cmd->height, cBuf, padlen);
+ ri.CL_WriteAVIVideoFrame(cmd->encodeBuffer, memcount);
+ }
+ else
+ {
+ byte *lineend, *memend;
+ byte *srcptr, *destptr;
+
+ srcptr = cBuf;
+ destptr = cmd->encodeBuffer;
+ memend = srcptr + memcount;
+
+ // swap R and B and remove line paddings
+ while(srcptr < memend)
+ {
+ lineend = srcptr + linelen;
+ while(srcptr < lineend)
+ {
+ *destptr++ = srcptr[2];
+ *destptr++ = srcptr[1];
+ *destptr++ = srcptr[0];
+ srcptr += 3;
+ }
+
+ Com_Memset(destptr, '\0', avipadlen);
+ destptr += avipadlen;
+
+ srcptr += padlen;
+ }
+
+ ri.CL_WriteAVIVideoFrame(cmd->encodeBuffer, avipadwidth * cmd->height);
+ }
+
+ return (const void *)(cmd + 1);
+}
+
+//============================================================================
+
+/*
+** GL_SetDefaultState
+*/
+void GL_SetDefaultState( void )
+{
+ qglClearDepth( 1.0f );
+
+ qglCullFace(GL_FRONT);
+
+ qglColor4f (1,1,1,1);
+
+ // initialize downstream texture unit if we're running
+ // in a multitexture environment
+ if ( qglActiveTextureARB ) {
+ GL_SelectTexture( 1 );
+ GL_TextureMode( r_textureMode->string );
+ GL_TexEnv( GL_MODULATE );
+ qglDisable( GL_TEXTURE_2D );
+ GL_SelectTexture( 0 );
+ }
+
+ qglEnable(GL_TEXTURE_2D);
+ GL_TextureMode( r_textureMode->string );
+ GL_TexEnv( GL_MODULATE );
+
+ qglShadeModel( GL_SMOOTH );
+ qglDepthFunc( GL_LEQUAL );
+
+ // the vertex array is always enabled, but the color and texture
+ // arrays are enabled and disabled around the compiled vertex array call
+ qglEnableClientState (GL_VERTEX_ARRAY);
+
+ //
+ // make sure our GL state vector is set correctly
+ //
+ glState.glStateBits = GLS_DEPTHTEST_DISABLE | GLS_DEPTHMASK_TRUE;
+
+ qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+ qglDepthMask( GL_TRUE );
+ qglDisable( GL_DEPTH_TEST );
+ qglEnable( GL_SCISSOR_TEST );
+ qglDisable( GL_CULL_FACE );
+ qglDisable( GL_BLEND );
+}
+
+
+/*
+================
+GfxInfo_f
+================
+*/
+void GfxInfo_f( void )
+{
+ const char *enablestrings[] =
+ {
+ "disabled",
+ "enabled"
+ };
+ const char *fsstrings[] =
+ {
+ "windowed",
+ "fullscreen"
+ };
+
+ ri.Printf( PRINT_ALL, "\nGL_VENDOR: %s\n", glConfig.vendor_string );
+ ri.Printf( PRINT_ALL, "GL_RENDERER: %s\n", glConfig.renderer_string );
+ ri.Printf( PRINT_ALL, "GL_VERSION: %s\n", glConfig.version_string );
+ ri.Printf( PRINT_ALL, "GL_EXTENSIONS: %s\n", glConfig.extensions_string );
+ ri.Printf( PRINT_ALL, "GL_MAX_TEXTURE_SIZE: %d\n", glConfig.maxTextureSize );
+ ri.Printf( PRINT_ALL, "GL_MAX_TEXTURE_UNITS_ARB: %d\n", glConfig.numTextureUnits );
+ ri.Printf( PRINT_ALL, "\nPIXELFORMAT: color(%d-bits) Z(%d-bit) stencil(%d-bits)\n", glConfig.colorBits, glConfig.depthBits, glConfig.stencilBits );
+ ri.Printf( PRINT_ALL, "MODE: %d x %d %s hz:", glConfig.vidWidth, glConfig.vidHeight, fsstrings[r_fullscreen->integer == 1] );
+ if ( glConfig.displayFrequency )
+ {
+ ri.Printf( PRINT_ALL, "%d\n", glConfig.displayFrequency );
+ }
+ else
+ {
+ ri.Printf( PRINT_ALL, "N/A\n" );
+ }
+ if ( glConfig.deviceSupportsGamma )
+ {
+ ri.Printf( PRINT_ALL, "GAMMA: hardware w/ %d overbright bits\n", tr.overbrightBits );
+ }
+ else
+ {
+ ri.Printf( PRINT_ALL, "GAMMA: software w/ %d overbright bits\n", tr.overbrightBits );
+ }
+
+ // rendering primitives
+ {
+ int primitives;
+
+ // default is to use triangles if compiled vertex arrays are present
+ ri.Printf( PRINT_ALL, "rendering primitives: " );
+ primitives = r_primitives->integer;
+ if ( primitives == 0 ) {
+ if ( qglLockArraysEXT ) {
+ primitives = 2;
+ } else {
+ primitives = 1;
+ }
+ }
+ if ( primitives == -1 ) {
+ ri.Printf( PRINT_ALL, "none\n" );
+ } else if ( primitives == 2 ) {
+ ri.Printf( PRINT_ALL, "single glDrawElements\n" );
+ } else if ( primitives == 1 ) {
+ ri.Printf( PRINT_ALL, "multiple glArrayElement\n" );
+ } else if ( primitives == 3 ) {
+ ri.Printf( PRINT_ALL, "multiple glColor4ubv + glTexCoord2fv + glVertex3fv\n" );
+ }
+ }
+
+ ri.Printf( PRINT_ALL, "texturemode: %s\n", r_textureMode->string );
+ ri.Printf( PRINT_ALL, "picmip: %d\n", r_picmip->integer );
+ ri.Printf( PRINT_ALL, "texture bits: %d\n", r_texturebits->integer );
+ ri.Printf( PRINT_ALL, "multitexture: %s\n", enablestrings[qglActiveTextureARB != 0] );
+ ri.Printf( PRINT_ALL, "compiled vertex arrays: %s\n", enablestrings[qglLockArraysEXT != 0 ] );
+ ri.Printf( PRINT_ALL, "texenv add: %s\n", enablestrings[glConfig.textureEnvAddAvailable != 0] );
+ ri.Printf( PRINT_ALL, "compressed textures: %s\n", enablestrings[glConfig.textureCompression!=TC_NONE] );
+ if ( r_vertexLight->integer || glConfig.hardwareType == GLHW_PERMEDIA2 )
+ {
+ ri.Printf( PRINT_ALL, "HACK: using vertex lightmap approximation\n" );
+ }
+ if ( glConfig.hardwareType == GLHW_RAGEPRO )
+ {
+ ri.Printf( PRINT_ALL, "HACK: ragePro approximations\n" );
+ }
+ if ( glConfig.hardwareType == GLHW_RIVA128 )
+ {
+ ri.Printf( PRINT_ALL, "HACK: riva128 approximations\n" );
+ }
+ if ( glConfig.smpActive ) {
+ ri.Printf( PRINT_ALL, "Using dual processor acceleration\n" );
+ }
+ if ( r_finish->integer ) {
+ ri.Printf( PRINT_ALL, "Forcing glFinish\n" );
+ }
+}
+
+/*
+===============
+R_Register
+===============
+*/
+void R_Register( void )
+{
+ //
+ // latched and archived variables
+ //
+ r_allowExtensions = ri.Cvar_Get( "r_allowExtensions", "1", CVAR_ARCHIVE | CVAR_LATCH );
+ r_ext_compressed_textures = ri.Cvar_Get( "r_ext_compressed_textures", "0", CVAR_ARCHIVE | CVAR_LATCH );
+ r_ext_multitexture = ri.Cvar_Get( "r_ext_multitexture", "1", CVAR_ARCHIVE | CVAR_LATCH );
+ r_ext_compiled_vertex_array = ri.Cvar_Get( "r_ext_compiled_vertex_array", "1", CVAR_ARCHIVE | CVAR_LATCH);
+ r_ext_texture_env_add = ri.Cvar_Get( "r_ext_texture_env_add", "1", CVAR_ARCHIVE | CVAR_LATCH);
+
+ r_picmip = ri.Cvar_Get ("r_picmip", GENERIC_HW_R_PICMIP_DEFAULT,
+ CVAR_ARCHIVE | CVAR_LATCH );
+ r_ext_texture_filter_anisotropic = ri.Cvar_Get( "r_ext_texture_filter_anisotropic",
+ "0", CVAR_ARCHIVE | CVAR_LATCH );
+ r_ext_max_anisotropy = ri.Cvar_Get( "r_ext_max_anisotropy", "2", CVAR_ARCHIVE | CVAR_LATCH );
+
+ r_roundImagesDown = ri.Cvar_Get ("r_roundImagesDown", "1", CVAR_ARCHIVE | CVAR_LATCH );
+ r_colorMipLevels = ri.Cvar_Get ("r_colorMipLevels", "0", CVAR_LATCH );
+ ri.Cvar_CheckRange( r_picmip, 0, 16, qtrue );
+ r_detailTextures = ri.Cvar_Get( "r_detailtextures", "1", CVAR_ARCHIVE | CVAR_LATCH );
+ r_texturebits = ri.Cvar_Get( "r_texturebits", "0", CVAR_ARCHIVE | CVAR_LATCH );
+ r_colorbits = ri.Cvar_Get( "r_colorbits", "0", CVAR_ARCHIVE | CVAR_LATCH );
+ r_stencilbits = ri.Cvar_Get( "r_stencilbits", "8", CVAR_ARCHIVE | CVAR_LATCH );
+ r_depthbits = ri.Cvar_Get( "r_depthbits", "0", CVAR_ARCHIVE | CVAR_LATCH );
+ r_ext_multisample = ri.Cvar_Get( "r_ext_multisample", "0", CVAR_ARCHIVE | CVAR_LATCH );
+ ri.Cvar_CheckRange( r_ext_multisample, 0, 4, qtrue );
+ r_overBrightBits = ri.Cvar_Get ("r_overBrightBits", "1", CVAR_ARCHIVE | CVAR_LATCH );
+ r_ignorehwgamma = ri.Cvar_Get( "r_ignorehwgamma", "0", CVAR_ARCHIVE | CVAR_LATCH);
+ r_fullscreen = ri.Cvar_Get( "r_fullscreen", "1", CVAR_ARCHIVE );
+ r_noborder = Cvar_Get("r_noborder", "0", CVAR_ARCHIVE);
+ r_width = ri.Cvar_Get( "r_width", "640", CVAR_ARCHIVE | CVAR_LATCH );
+ r_height = ri.Cvar_Get( "r_height", "480", CVAR_ARCHIVE | CVAR_LATCH );
+ r_pixelAspect = ri.Cvar_Get( "r_pixelAspect", "1", CVAR_ARCHIVE | CVAR_LATCH );
+ r_simpleMipMaps = ri.Cvar_Get( "r_simpleMipMaps", "1", CVAR_ARCHIVE | CVAR_LATCH );
+ r_vertexLight = ri.Cvar_Get( "r_vertexLight", "0", CVAR_ARCHIVE | CVAR_LATCH );
+ r_uiFullScreen = ri.Cvar_Get( "r_uifullscreen", "0", 0);
+ r_subdivisions = ri.Cvar_Get ("r_subdivisions", "4", CVAR_ARCHIVE | CVAR_LATCH);
+ r_smp = ri.Cvar_Get( "r_smp", "0", CVAR_ARCHIVE | CVAR_LATCH);
+ r_stereoEnabled = ri.Cvar_Get( "r_stereoEnabled", "0", CVAR_ARCHIVE | CVAR_LATCH);
+ r_ignoreFastPath = ri.Cvar_Get( "r_ignoreFastPath", "1", CVAR_ARCHIVE | CVAR_LATCH );
+ r_greyscale = ri.Cvar_Get("r_greyscale", "0", CVAR_ARCHIVE | CVAR_LATCH);
+ ri.Cvar_CheckRange(r_greyscale, 0, 1, qfalse);
+
+ //
+ // temporary latched variables that can only change over a restart
+ //
+ r_fullbright = ri.Cvar_Get ("r_fullbright", "0", CVAR_LATCH|CVAR_CHEAT );
+ r_mapOverBrightBits = ri.Cvar_Get ("r_mapOverBrightBits", "2", CVAR_LATCH );
+ r_intensity = ri.Cvar_Get ("r_intensity", "1", CVAR_LATCH );
+ r_singleShader = ri.Cvar_Get ("r_singleShader", "0", CVAR_CHEAT | CVAR_LATCH );
+
+ //
+ // archived variables that can change at any time
+ //
+ r_lodCurveError = ri.Cvar_Get( "r_lodCurveError", "250", CVAR_ARCHIVE|CVAR_CHEAT );
+ r_lodbias = ri.Cvar_Get( "r_lodbias", "0", CVAR_ARCHIVE );
+ r_flares = ri.Cvar_Get ("r_flares", "0", CVAR_ARCHIVE );
+ r_znear = ri.Cvar_Get( "r_znear", "1", CVAR_CHEAT );
+ ri.Cvar_CheckRange( r_znear, 0.001f, 200, qfalse );
+ r_zproj = ri.Cvar_Get( "r_zproj", "64", CVAR_ARCHIVE );
+ r_stereoSeparation = ri.Cvar_Get( "r_stereoSeparation", "64", CVAR_ARCHIVE );
+ r_ignoreGLErrors = ri.Cvar_Get( "r_ignoreGLErrors", "1", CVAR_ARCHIVE );
+ r_fastsky = ri.Cvar_Get( "r_fastsky", "0", CVAR_ARCHIVE );
+ r_inGameVideo = ri.Cvar_Get( "r_inGameVideo", "1", CVAR_ARCHIVE );
+ r_drawSun = ri.Cvar_Get( "r_drawSun", "0", CVAR_ARCHIVE );
+ r_dynamiclight = ri.Cvar_Get( "r_dynamiclight", "1", CVAR_ARCHIVE );
+ r_dlightBacks = ri.Cvar_Get( "r_dlightBacks", "1", CVAR_ARCHIVE );
+ r_finish = ri.Cvar_Get ("r_finish", "0", CVAR_ARCHIVE);
+ r_textureMode = ri.Cvar_Get( "r_textureMode",
+ GENERIC_HW_R_TEXTUREMODE_DEFAULT, CVAR_ARCHIVE );
+ r_swapInterval = ri.Cvar_Get( "r_swapInterval", "0",
+ CVAR_ARCHIVE | CVAR_LATCH );
+ r_gamma = ri.Cvar_Get( "r_gamma", "1", CVAR_ARCHIVE );
+ r_facePlaneCull = ri.Cvar_Get ("r_facePlaneCull", "1", CVAR_ARCHIVE );
+
+ r_railWidth = ri.Cvar_Get( "r_railWidth", "16", CVAR_ARCHIVE );
+ r_railCoreWidth = ri.Cvar_Get( "r_railCoreWidth", "6", CVAR_ARCHIVE );
+ r_railSegmentLength = ri.Cvar_Get( "r_railSegmentLength", "32", CVAR_ARCHIVE );
+
+ r_primitives = ri.Cvar_Get( "r_primitives", "0", CVAR_ARCHIVE );
+
+ r_ambientScale = ri.Cvar_Get( "r_ambientScale", "0.6", CVAR_CHEAT );
+ r_directedScale = ri.Cvar_Get( "r_directedScale", "1", CVAR_CHEAT );
+
+ r_anaglyphMode = ri.Cvar_Get("r_anaglyphMode", "0", CVAR_ARCHIVE);
+
+ //
+ // temporary variables that can change at any time
+ //
+ r_showImages = ri.Cvar_Get( "r_showImages", "0", CVAR_TEMP );
+
+ r_debugLight = ri.Cvar_Get( "r_debuglight", "0", CVAR_TEMP );
+ r_debugSort = ri.Cvar_Get( "r_debugSort", "0", CVAR_CHEAT );
+ r_printShaders = ri.Cvar_Get( "r_printShaders", "0", 0 );
+ r_saveFontData = ri.Cvar_Get( "r_saveFontData", "0", 0 );
+
+ r_nocurves = ri.Cvar_Get ("r_nocurves", "0", CVAR_CHEAT );
+ r_drawworld = ri.Cvar_Get ("r_drawworld", "1", CVAR_CHEAT );
+ r_lightmap = ri.Cvar_Get ("r_lightmap", "0", CVAR_CHEAT );
+ r_portalOnly = ri.Cvar_Get ("r_portalOnly", "0", CVAR_CHEAT );
+
+ r_flareSize = ri.Cvar_Get ("r_flareSize", "40", CVAR_CHEAT);
+ r_flareFade = ri.Cvar_Get ("r_flareFade", "7", CVAR_CHEAT);
+ r_flareCoeff = ri.Cvar_Get ("r_flareCoeff", FLARE_STDCOEFF, CVAR_CHEAT);
+
+ r_showSmp = ri.Cvar_Get ("r_showSmp", "0", CVAR_CHEAT);
+ r_skipBackEnd = ri.Cvar_Get ("r_skipBackEnd", "0", CVAR_CHEAT);
+
+ r_measureOverdraw = ri.Cvar_Get( "r_measureOverdraw", "0", CVAR_CHEAT );
+ r_lodscale = ri.Cvar_Get( "r_lodscale", "5", CVAR_CHEAT );
+ r_norefresh = ri.Cvar_Get ("r_norefresh", "0", CVAR_CHEAT);
+ r_drawentities = ri.Cvar_Get ("r_drawentities", "1", CVAR_CHEAT );
+ r_ignore = ri.Cvar_Get( "r_ignore", "1", CVAR_CHEAT );
+ r_nocull = ri.Cvar_Get ("r_nocull", "0", CVAR_CHEAT);
+ r_novis = ri.Cvar_Get ("r_novis", "0", CVAR_CHEAT);
+ r_showcluster = ri.Cvar_Get ("r_showcluster", "0", CVAR_CHEAT);
+ r_speeds = ri.Cvar_Get ("r_speeds", "0", CVAR_CHEAT);
+ r_verbose = ri.Cvar_Get( "r_verbose", "0", CVAR_CHEAT );
+ r_logFile = ri.Cvar_Get( "r_logFile", "0", CVAR_CHEAT );
+ r_debugSurface = ri.Cvar_Get ("r_debugSurface", "0", CVAR_CHEAT);
+ r_nobind = ri.Cvar_Get ("r_nobind", "0", CVAR_CHEAT);
+ r_showtris = ri.Cvar_Get ("r_showtris", "0", CVAR_CHEAT);
+ r_showsky = ri.Cvar_Get ("r_showsky", "0", CVAR_CHEAT);
+ r_shownormals = ri.Cvar_Get ("r_shownormals", "0", CVAR_CHEAT);
+ r_clear = ri.Cvar_Get ("r_clear", "0", CVAR_CHEAT);
+ r_offsetFactor = ri.Cvar_Get( "r_offsetfactor", "-1", CVAR_CHEAT );
+ r_offsetUnits = ri.Cvar_Get( "r_offsetunits", "-2", CVAR_CHEAT );
+ r_drawBuffer = ri.Cvar_Get( "r_drawBuffer", "GL_BACK", CVAR_CHEAT );
+ r_lockpvs = ri.Cvar_Get ("r_lockpvs", "0", CVAR_CHEAT);
+ r_noportals = ri.Cvar_Get ("r_noportals", "0", CVAR_CHEAT);
+ r_shadows = ri.Cvar_Get( "cg_shadows", "1", 0 );
+
+ r_marksOnTriangleMeshes = ri.Cvar_Get("r_marksOnTriangleMeshes", "0", CVAR_ARCHIVE);
+
+ r_aviMotionJpegQuality = ri.Cvar_Get("r_aviMotionJpegQuality", "90", CVAR_ARCHIVE);
+ r_screenshotJpegQuality = ri.Cvar_Get("r_screenshotJpegQuality", "90", CVAR_ARCHIVE);
+
+ r_maxpolys = ri.Cvar_Get( "r_maxpolys", va("%d", MAX_POLYS), 0);
+ r_maxpolyverts = ri.Cvar_Get( "r_maxpolyverts", va("%d", MAX_POLYVERTS), 0);
+
+ // make sure all the commands added here are also
+ // removed in R_Shutdown
+ ri.Cmd_AddCommand( "imagelist", R_ImageList_f );
+ ri.Cmd_AddCommand( "shaderlist", R_ShaderList_f );
+ ri.Cmd_AddCommand( "skinlist", R_SkinList_f );
+ ri.Cmd_AddCommand( "modellist", R_Modellist_f );
+ ri.Cmd_AddCommand( "screenshot", R_ScreenShot_f );
+ ri.Cmd_AddCommand( "screenshotJPEG", R_ScreenShotJPEG_f );
+ ri.Cmd_AddCommand( "gfxinfo", GfxInfo_f );
+}
+
+/*
+===============
+R_Init
+===============
+*/
+void R_Init( void ) {
+ int err;
+ int i;
+ byte *ptr;
+
+ ri.Printf( PRINT_ALL, "----- R_Init -----\n" );
+
+ // clear all our internal state
+ Com_Memset( &tr, 0, sizeof( tr ) );
+ Com_Memset( &backEnd, 0, sizeof( backEnd ) );
+ Com_Memset( &tess, 0, sizeof( tess ) );
+
+// Swap_Init();
+
+ if ( (intptr_t)tess.xyz & 15 ) {
+ Com_Printf( "WARNING: tess.xyz not 16 byte aligned\n" );
+ }
+ Com_Memset( tess.constantColor255, 255, sizeof( tess.constantColor255 ) );
+
+ //
+ // init function tables
+ //
+ for ( i = 0; i < FUNCTABLE_SIZE; i++ )
+ {
+ tr.sinTable[i] = sin( DEG2RAD( i * 360.0f / ( ( float ) ( FUNCTABLE_SIZE - 1 ) ) ) );
+ tr.squareTable[i] = ( i < FUNCTABLE_SIZE/2 ) ? 1.0f : -1.0f;
+ tr.sawToothTable[i] = (float)i / FUNCTABLE_SIZE;
+ tr.inverseSawToothTable[i] = 1.0f - tr.sawToothTable[i];
+
+ if ( i < FUNCTABLE_SIZE / 2 )
+ {
+ if ( i < FUNCTABLE_SIZE / 4 )
+ {
+ tr.triangleTable[i] = ( float ) i / ( FUNCTABLE_SIZE / 4 );
+ }
+ else
+ {
+ tr.triangleTable[i] = 1.0f - tr.triangleTable[i-FUNCTABLE_SIZE / 4];
+ }
+ }
+ else
+ {
+ tr.triangleTable[i] = -tr.triangleTable[i-FUNCTABLE_SIZE/2];
+ }
+ }
+
+ R_InitFogTable();
+
+ R_NoiseInit();
+
+ R_Register();
+
+ max_polys = r_maxpolys->integer;
+ if (max_polys < MAX_POLYS)
+ max_polys = MAX_POLYS;
+
+ max_polyverts = r_maxpolyverts->integer;
+ if (max_polyverts < MAX_POLYVERTS)
+ max_polyverts = MAX_POLYVERTS;
+
+ ptr = ri.Hunk_Alloc( sizeof( *backEndData[0] ) + sizeof(srfPoly_t) * max_polys + sizeof(polyVert_t) * max_polyverts, h_low);
+ backEndData[0] = (backEndData_t *) ptr;
+ backEndData[0]->polys = (srfPoly_t *) ((char *) ptr + sizeof( *backEndData[0] ));
+ backEndData[0]->polyVerts = (polyVert_t *) ((char *) ptr + sizeof( *backEndData[0] ) + sizeof(srfPoly_t) * max_polys);
+ if ( r_smp->integer ) {
+ ptr = ri.Hunk_Alloc( sizeof( *backEndData[1] ) + sizeof(srfPoly_t) * max_polys + sizeof(polyVert_t) * max_polyverts, h_low);
+ backEndData[1] = (backEndData_t *) ptr;
+ backEndData[1]->polys = (srfPoly_t *) ((char *) ptr + sizeof( *backEndData[1] ));
+ backEndData[1]->polyVerts = (polyVert_t *) ((char *) ptr + sizeof( *backEndData[1] ) + sizeof(srfPoly_t) * max_polys);
+ } else {
+ backEndData[1] = NULL;
+ }
+ R_ToggleSmpFrame();
+
+ InitOpenGL();
+
+ R_InitImages();
+
+ R_InitShaders();
+
+ R_InitSkins();
+
+ R_ModelInit();
+
+ R_InitFreeType();
+
+
+ err = qglGetError();
+ if ( err != GL_NO_ERROR )
+ ri.Printf (PRINT_ALL, "glGetError() = 0x%x\n", err);
+
+ ri.Printf( PRINT_ALL, "----- finished R_Init -----\n" );
+}
+
+/*
+===============
+RE_Shutdown
+===============
+*/
+void RE_Shutdown( qboolean destroyWindow ) {
+
+ ri.Printf( PRINT_ALL, "RE_Shutdown( %i )\n", destroyWindow );
+
+ ri.Cmd_RemoveCommand ("modellist");
+ ri.Cmd_RemoveCommand ("screenshotJPEG");
+ ri.Cmd_RemoveCommand ("screenshot");
+ ri.Cmd_RemoveCommand ("imagelist");
+ ri.Cmd_RemoveCommand ("shaderlist");
+ ri.Cmd_RemoveCommand ("skinlist");
+ ri.Cmd_RemoveCommand ("gfxinfo");
+ ri.Cmd_RemoveCommand( "modelist" );
+ ri.Cmd_RemoveCommand( "shaderstate" );
+
+
+ if ( tr.registered ) {
+ R_SyncRenderThread();
+ R_ShutdownCommandBuffers();
+ R_DeleteTextures();
+ }
+
+ R_DoneFreeType();
+
+ // shut down platform specific OpenGL stuff
+ if ( destroyWindow ) {
+ GLimp_Shutdown();
+ }
+
+ tr.registered = qfalse;
+}
+
+
+/*
+=============
+RE_EndRegistration
+
+Touch all images to make sure they are resident
+=============
+*/
+void RE_EndRegistration( void ) {
+ R_SyncRenderThread();
+ if (!Sys_LowPhysicalMemory()) {
+ RB_ShowImages();
+ }
+}
+
+
+/*
+@@@@@@@@@@@@@@@@@@@@@
+GetRefAPI
+
+@@@@@@@@@@@@@@@@@@@@@
+*/
+refexport_t *GetRefAPI ( int apiVersion, refimport_t *rimp ) {
+ static refexport_t re;
+
+ ri = *rimp;
+
+ Com_Memset( &re, 0, sizeof( re ) );
+
+ if ( apiVersion != REF_API_VERSION ) {
+ ri.Printf(PRINT_ALL, "Mismatched REF_API_VERSION: expected %i, got %i\n",
+ REF_API_VERSION, apiVersion );
+ return NULL;
+ }
+
+ // the RE_ functions are Renderer Entry points
+
+ re.Shutdown = RE_Shutdown;
+
+ re.BeginRegistration = RE_BeginRegistration;
+ re.RegisterModel = RE_RegisterModel;
+ re.RegisterSkin = RE_RegisterSkin;
+ re.RegisterShader = RE_RegisterShader;
+ re.RegisterShaderNoMip = RE_RegisterShaderNoMip;
+ re.LoadWorld = RE_LoadWorldMap;
+ re.SetWorldVisData = RE_SetWorldVisData;
+ re.EndRegistration = RE_EndRegistration;
+
+ re.BeginFrame = RE_BeginFrame;
+ re.EndFrame = RE_EndFrame;
+
+ re.MarkFragments = R_MarkFragments;
+ re.LerpTag = R_LerpTag;
+ re.ModelBounds = R_ModelBounds;
+
+ re.ClearScene = RE_ClearScene;
+ re.AddRefEntityToScene = RE_AddRefEntityToScene;
+ re.AddPolyToScene = RE_AddPolyToScene;
+ re.LightForPoint = R_LightForPoint;
+ re.AddLightToScene = RE_AddLightToScene;
+ re.AddAdditiveLightToScene = RE_AddAdditiveLightToScene;
+ re.RenderScene = RE_RenderScene;
+
+ re.SetColor = RE_SetColor;
+ re.SetClipRegion = RE_SetClipRegion;
+ re.DrawStretchPic = RE_StretchPic;
+ re.DrawStretchRaw = RE_StretchRaw;
+ re.UploadCinematic = RE_UploadCinematic;
+
+ re.RegisterFont = RE_RegisterFont;
+ re.RemapShader = R_RemapShader;
+ re.GetEntityToken = R_GetEntityToken;
+ re.inPVS = R_inPVS;
+
+ re.TakeVideoFrame = RE_TakeVideoFrame;
+
+ return &re;
+}