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