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