rewrote memory system entirely (hunk, cache, and zone are gone, memory pools replaced...
[xonotic/darkplaces.git] / gl_screen.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20
21 // screen.c -- master for refresh, status bar, console, chat, notify, etc
22
23 #include "quakedef.h"
24
25 /*
26
27 background clear
28 rendering
29 turtle/net/ram icons
30 sbar
31 centerprint / slow centerprint
32 notify lines
33 intermission / finale overlay
34 loading plaque
35 console
36 menu
37
38 required background clears
39 required update regions
40
41
42 syncronous draw mode or async
43 One off screen buffer, with updates either copied or xblited
44 Need to double buffer?
45
46
47 async draw will require the refresh area to be cleared, because it will be
48 xblited, but sync draw can just ignore it.
49
50 sync
51 draw
52
53 CenterPrint ()
54 SlowPrint ()
55 Screen_Update ();
56 Con_Printf ();
57
58 net
59 turn off messages option
60
61 the refresh is always rendered, unless the console is full screen
62
63
64 console is:
65         notify lines
66         half
67         full
68
69
70 */
71
72
73 float   scr_con_current;
74 float   scr_conlines;           // lines of console to display
75
76 float   oldscreensize, oldfov;
77 cvar_t  scr_viewsize = {CVAR_SAVE, "viewsize","100"};
78 cvar_t  scr_fov = {CVAR_SAVE, "fov","90"};      // 10 - 170
79 cvar_t  scr_conspeed = {CVAR_SAVE, "scr_conspeed","900"}; // LordHavoc: quake used 300
80 cvar_t  scr_centertime = {0, "scr_centertime","2"};
81 cvar_t  scr_showram = {CVAR_SAVE, "showram","1"};
82 cvar_t  scr_showturtle = {CVAR_SAVE, "showturtle","0"};
83 cvar_t  scr_showpause = {CVAR_SAVE, "showpause","1"};
84 cvar_t  scr_printspeed = {0, "scr_printspeed","8"};
85 cvar_t  showfps = {CVAR_SAVE, "showfps", "0"};
86 cvar_t  r_render = {0, "r_render", "1"};
87 cvar_t  r_brightness = {CVAR_SAVE, "r_brightness", "1"}; // LordHavoc: a method of operating system independent color correction
88 cvar_t  r_contrast = {CVAR_SAVE, "r_contrast", "1"}; // LordHavoc: a method of operating system independent color correction
89 cvar_t  gl_dither = {CVAR_SAVE, "gl_dither", "1"}; // whether or not to use dithering
90
91 qboolean        scr_initialized;                // ready to draw
92
93 int                     clearconsole;
94 int                     clearnotify;
95
96 int                     lightscalebit;
97 float           lightscale;
98
99 qboolean        scr_disabled_for_loading;
100 //qboolean      scr_drawloading;
101 //float         scr_disabled_time;
102
103 void SCR_ScreenShot_f (void);
104
105 /*
106 ===============================================================================
107
108 CENTER PRINTING
109
110 ===============================================================================
111 */
112
113 char            scr_centerstring[1024];
114 float           scr_centertime_start;   // for slow victory printing
115 float           scr_centertime_off;
116 int                     scr_center_lines;
117 int                     scr_erase_lines;
118 int                     scr_erase_center;
119
120 /*
121 ==============
122 SCR_CenterPrint
123
124 Called for important messages that should stay in the center of the screen
125 for a few moments
126 ==============
127 */
128 void SCR_CenterPrint (char *str)
129 {
130         strncpy (scr_centerstring, str, sizeof(scr_centerstring)-1);
131         scr_centertime_off = scr_centertime.value;
132         scr_centertime_start = cl.time;
133
134 // count the number of lines for centering
135         scr_center_lines = 1;
136         while (*str)
137         {
138                 if (*str == '\n')
139                         scr_center_lines++;
140                 str++;
141         }
142 }
143
144
145 void SCR_DrawCenterString (void)
146 {
147         char    *start;
148         int             l;
149         int             x, y;
150         int             remaining;
151
152 // the finale prints the characters one at a time
153         if (cl.intermission)
154                 remaining = scr_printspeed.value * (cl.time - scr_centertime_start);
155         else
156                 remaining = 9999;
157
158         scr_erase_center = 0;
159         start = scr_centerstring;
160
161         if (scr_center_lines <= 4)
162                 y = vid.conheight*0.35;
163         else
164                 y = 48;
165
166         do      
167         {
168         // scan the width of the line
169                 for (l=0 ; l<40 ; l++)
170                         if (start[l] == '\n' || !start[l])
171                                 break;
172                 x = (vid.conwidth - l*8)/2;
173                 // LordHavoc: speedup
174                 if (l > 0)
175                 {
176                         if (remaining < l)
177                                 l = remaining;
178                         Draw_String(x, y, start, l);
179                         remaining -= l;
180                         if (remaining <= 0)
181                                 return;
182                 }
183                 /*
184                 for (j=0 ; j<l ; j++, x+=8)
185                 {
186                         Draw_Character (x, y, start[j]);        
187                         if (!remaining--)
188                                 return;
189                 }
190                 */
191                         
192                 y += 8;
193
194                 while (*start && *start != '\n')
195                         start++;
196
197                 if (!*start)
198                         break;
199                 start++;                // skip the \n
200         } while (1);
201 }
202
203 void SCR_CheckDrawCenterString (void)
204 {
205         if (scr_center_lines > scr_erase_lines)
206                 scr_erase_lines = scr_center_lines;
207
208         scr_centertime_off -= host_frametime;
209
210         if (scr_centertime_off <= 0 && !cl.intermission)
211                 return;
212         if (key_dest != key_game)
213                 return;
214
215         SCR_DrawCenterString ();
216 }
217
218 //=============================================================================
219
220 /*
221 ====================
222 CalcFov
223 ====================
224 */
225 float CalcFov (float fov_x, float width, float height)
226 {
227         // calculate vision size and alter by aspect, then convert back to angle
228         return atan (height / (width / tan(fov_x/360*M_PI))) * 360 / M_PI;
229 }
230
231 /*
232 =================
233 SCR_CalcRefdef
234
235 Must be called whenever vid changes
236 Internal use only
237 =================
238 */
239 static void SCR_CalcRefdef (void)
240 {
241         float size;
242
243 //      vid.recalc_refdef = 0;
244
245 //========================================
246
247 // bound viewsize
248         if (scr_viewsize.value < 30)
249                 Cvar_Set ("viewsize","30");
250         if (scr_viewsize.value > 120)
251                 Cvar_Set ("viewsize","120");
252
253 // bound field of view
254         if (scr_fov.value < 10)
255                 Cvar_Set ("fov","10");
256         if (scr_fov.value > 170)
257                 Cvar_Set ("fov","170");
258
259 // intermission is always full screen
260         if (cl.intermission)
261         {
262                 size = 1;
263                 sb_lines = 0;
264         }
265         else
266         {
267                 if (scr_viewsize.value >= 120)
268                         sb_lines = 0;           // no status bar at all
269                 else if (scr_viewsize.value >= 110)
270                         sb_lines = 24;          // no inventory
271                 else
272                         sb_lines = 24+16+8;
273                 size = scr_viewsize.value * (1.0 / 100.0);
274         }
275
276         if (size >= 1)
277         {
278                 r_refdef.width = vid.realwidth;
279                 r_refdef.height = vid.realheight;
280                 r_refdef.x = 0;
281                 r_refdef.y = 0;
282         }
283         else
284         {
285                 r_refdef.width = vid.realwidth * size;
286                 r_refdef.height = vid.realheight * size;
287                 r_refdef.x = (vid.realwidth - r_refdef.width)/2;
288                 r_refdef.y = (vid.realheight - r_refdef.height)/2;
289         }
290
291         r_refdef.fov_x = scr_fov.value;
292         r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.width, r_refdef.height);
293
294         r_refdef.width = bound(0, r_refdef.width, vid.realwidth);
295         r_refdef.height = bound(0, r_refdef.height, vid.realheight);
296         r_refdef.x = bound(0, r_refdef.x, vid.realwidth) + vid.realx;
297         r_refdef.y = bound(0, r_refdef.y, vid.realheight) + vid.realy;
298 }
299
300
301 /*
302 =================
303 SCR_SizeUp_f
304
305 Keybinding command
306 =================
307 */
308 void SCR_SizeUp_f (void)
309 {
310         Cvar_SetValue ("viewsize",scr_viewsize.value+10);
311 //      vid.recalc_refdef = 1;
312 }
313
314
315 /*
316 =================
317 SCR_SizeDown_f
318
319 Keybinding command
320 =================
321 */
322 void SCR_SizeDown_f (void)
323 {
324         Cvar_SetValue ("viewsize",scr_viewsize.value-10);
325 //      vid.recalc_refdef = 1;
326 }
327
328 //============================================================================
329
330 void gl_screen_start(void)
331 {
332 }
333
334 void gl_screen_shutdown(void)
335 {
336 }
337
338 void gl_screen_newmap(void)
339 {
340 }
341
342 /*
343 ==================
344 SCR_Init
345 ==================
346 */
347 static void R_Envmap_f (void);
348 void GL_Screen_Init (void)
349 {
350         Cvar_RegisterVariable (&scr_fov);
351         Cvar_RegisterVariable (&scr_viewsize);
352         Cvar_RegisterVariable (&scr_conspeed);
353         Cvar_RegisterVariable (&scr_showram);
354         Cvar_RegisterVariable (&scr_showturtle);
355         Cvar_RegisterVariable (&scr_showpause);
356         Cvar_RegisterVariable (&scr_centertime);
357         Cvar_RegisterVariable (&scr_printspeed);
358         Cvar_RegisterVariable (&showfps);
359         Cvar_RegisterVariable (&r_render);
360         Cvar_RegisterVariable (&r_brightness);
361         Cvar_RegisterVariable (&r_contrast);
362         Cvar_RegisterVariable (&gl_dither);
363 #ifdef NORENDER
364         Cvar_SetValue("r_render", 0);
365 #endif
366
367 //
368 // register our commands
369 //
370         Cmd_AddCommand ("screenshot",SCR_ScreenShot_f);
371         Cmd_AddCommand ("envmap", R_Envmap_f);
372         Cmd_AddCommand ("sizeup",SCR_SizeUp_f);
373         Cmd_AddCommand ("sizedown",SCR_SizeDown_f);
374
375         scr_initialized = true;
376
377         R_RegisterModule("GL_Screen", gl_screen_start, gl_screen_shutdown, gl_screen_newmap);
378 }
379
380
381
382 /*
383 ==============
384 SCR_DrawRam
385 ==============
386 */
387 void SCR_DrawRam (void)
388 {
389 //      if (!scr_showram.integer)
390 //              return;
391 //      Draw_Pic (32, 0, Draw_CachePic("ram"));
392 }
393
394 /*
395 ==============
396 SCR_DrawTurtle
397 ==============
398 */
399 void SCR_DrawTurtle (void)
400 {
401         static int      count;
402
403         if (!scr_showturtle.integer)
404                 return;
405
406         if (host_frametime < 0.1)
407         {
408                 count = 0;
409                 return;
410         }
411
412         count++;
413         if (count < 3)
414                 return;
415
416         Draw_Pic (0, 0, Draw_CachePic("turtle"));
417 }
418
419 /*
420 ==============
421 SCR_DrawNet
422 ==============
423 */
424 void SCR_DrawNet (void)
425 {
426         if (realtime - cl.last_received_message < 0.3)
427                 return;
428         if (cls.demoplayback)
429                 return;
430
431         Draw_Pic (64, 0, Draw_CachePic("net"));
432 }
433
434 /*
435 ==============
436 DrawPause
437 ==============
438 */
439 void SCR_DrawPause (void)
440 {
441         qpic_t  *pic;
442
443         if (!scr_showpause.integer)             // turn off for screenshots
444                 return;
445
446         if (!cl.paused)
447                 return;
448
449         pic = Draw_CachePic ("gfx/pause.lmp");
450         Draw_Pic ((vid.conwidth - pic->width)/2, (vid.conheight - pic->height)/2, pic);
451 }
452
453
454
455 /*
456 ==============
457 SCR_DrawLoading
458 ==============
459 */
460 /*
461 void SCR_DrawLoading (void)
462 {
463         qpic_t  *pic;
464
465         if (!scr_drawloading)
466                 return;
467                 
468         pic = Draw_CachePic ("gfx/loading.lmp");
469         Draw_Pic ((vid.conwidth - pic->width)/2, (vid.conheight - pic->height)/2, pic);
470 }
471 */
472
473
474
475 //=============================================================================
476
477
478 /*
479 ==================
480 SCR_SetUpToDrawConsole
481 ==================
482 */
483 void SCR_SetUpToDrawConsole (void)
484 {
485         Con_CheckResize ();
486         
487         //if (scr_drawloading)
488         //      return;         // never a console with loading plaque
489
490 // decide on the height of the console
491         con_forcedup = !cl.worldmodel || cls.signon != SIGNONS;
492
493         if (con_forcedup)
494         {
495                 scr_conlines = vid.conheight;           // full screen
496                 scr_con_current = scr_conlines;
497         }
498         else if (key_dest == key_console)
499                 scr_conlines = vid.conheight/2; // half screen
500         else
501                 scr_conlines = 0;                               // none visible
502
503         if (scr_conlines < scr_con_current)
504         {
505                 scr_con_current -= scr_conspeed.value*host_realframetime;
506                 if (scr_conlines > scr_con_current)
507                         scr_con_current = scr_conlines;
508
509         }
510         else if (scr_conlines > scr_con_current)
511         {
512                 scr_con_current += scr_conspeed.value*host_realframetime;
513                 if (scr_conlines < scr_con_current)
514                         scr_con_current = scr_conlines;
515         }
516 }
517
518 /*
519 ==================
520 SCR_DrawConsole
521 ==================
522 */
523 void SCR_DrawConsole (void)
524 {
525         if (scr_con_current)
526         {
527                 Con_DrawConsole (scr_con_current, true);
528                 clearconsole = 0;
529         }
530         else
531         {
532                 if (key_dest == key_game || key_dest == key_message)
533                         Con_DrawNotify ();      // only draw notify in game
534         }
535 }
536
537
538 /*
539 ============================================================================== 
540
541                                                 SCREEN SHOTS 
542
543 ============================================================================== 
544 */ 
545
546 /*
547 ==================
548 SCR_ScreenShot_f
549 ==================
550 */
551 void SCR_ScreenShot_f (void)
552 {
553         byte            *buffer, gamma[256];
554         char            filename[80];
555         char            checkname[MAX_OSPATH];
556         int                     i;
557 //
558 // find a file name to save it to
559 //
560         strcpy(filename,"dp0000.tga");
561
562         for (i=0 ; i<=9999 ; i++)
563         {
564                 filename[2] = (i/1000)%10 + '0';
565                 filename[3] = (i/ 100)%10 + '0';
566                 filename[4] = (i/  10)%10 + '0';
567                 filename[5] = (i/   1)%10 + '0';
568                 sprintf (checkname, "%s/%s", com_gamedir, filename);
569                 if (Sys_FileTime(checkname) == -1)
570                         break;  // file doesn't exist
571         }
572         if (i==10000)
573         {
574                 Con_Printf ("SCR_ScreenShot_f: Couldn't create a TGA file\n");
575                 return;
576         }
577
578         buffer = Mem_Alloc(tempmempool, vid.realwidth*vid.realheight*3);
579         glReadPixels (vid.realx, vid.realy, vid.realwidth, vid.realheight, GL_RGB, GL_UNSIGNED_BYTE, buffer);
580         CHECKGLERROR
581
582         // apply hardware gamma to the image
583         BuildGammaTable8((lighthalf && hardwaregammasupported) ? 2.0f : 1.0f, 1, 1, 0, gamma);
584         Image_GammaRemapRGB(buffer, buffer, vid.realwidth*vid.realheight, gamma, gamma, gamma);
585
586         Image_WriteTGARGB_preflipped(filename, vid.realwidth, vid.realheight, buffer);
587
588         Mem_Free(buffer);
589         Con_Printf ("Wrote %s\n", filename);
590 }
591
592 /*
593 ===============
594 R_Envmap_f
595
596 Grab six views for environment mapping tests
597 ===============
598 */
599 float CalcFov (float fov_x, float width, float height);
600 struct
601 {
602         float angles[3];
603         char *name;
604 }
605 envmapinfo[6] =
606 {
607         {{  0,   0, 0}, "ft"},
608         {{  0,  90, 0}, "rt"},
609         {{  0, 180, 0}, "bk"},
610         {{  0, 270, 0}, "lf"},
611         {{-90,  90, 0}, "up"},
612         {{ 90,  90, 0}, "dn"}
613 };
614 static void R_Envmap_f (void)
615 {
616         int             i, size;
617         char    filename[256];
618         char    basename[256];
619         byte    *buffer, gamma[256];
620
621         if (Cmd_Argc() != 3)
622         {
623                 Con_Printf ("envmap <basename> <size>: save out 6 cubic environment map images, usable with loadsky, note that size must one of 128, 256, 512, or 1024 and can't be bigger than your current resolution\n");
624                 return;
625         }
626
627         if (!r_render.integer)
628                 return;
629
630         strcpy(basename, Cmd_Argv(1));
631         size = atoi(Cmd_Argv(2));
632         if (size != 128 && size != 256 && size != 512 && size != 1024)
633         {
634                 Con_Printf("envmap: size must be one of 128, 256, 512, or 1024\n");
635                 return;
636         }
637         if (size > vid.realwidth || size > vid.realheight)
638         {
639                 Con_Printf("envmap: your resolution is not big enough to render that size\n");
640                 return;
641         }
642
643         buffer = Mem_Alloc(tempmempool, size*size*3);
644         if (buffer == NULL)
645         {
646                 Con_Printf("envmap: unable to allocate memory for image\n");
647                 return;
648         }
649
650         BuildGammaTable8((lighthalf && hardwaregammasupported) ? 2.0f : 1.0f, 1, 1, 0, gamma);
651
652 //      glDrawBuffer  (GL_FRONT);
653 //      glReadBuffer  (GL_FRONT);
654         glDrawBuffer  (GL_BACK);
655         glReadBuffer  (GL_BACK);
656         envmap = true;
657
658         r_refdef.x = 0;
659         r_refdef.y = 0;
660         r_refdef.width = size;
661         r_refdef.height = size;
662
663         r_refdef.fov_x = 90;
664         r_refdef.fov_y = 90;
665
666         for (i = 0;i < 6;i++)
667         {
668                 VectorCopy(envmapinfo[i].angles, r_refdef.viewangles);
669                 glClearColor(0,0,0,0);
670                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: clear the screen (around the view as well)
671                 R_RenderView ();
672                 glReadPixels (0, 0, size, size, GL_RGB, GL_UNSIGNED_BYTE, buffer);
673                 sprintf(filename, "env/%s%s.tga", basename, envmapinfo[i].name);
674                 Image_GammaRemapRGB(buffer, buffer, size * size, gamma, gamma, gamma);
675                 Image_WriteTGARGB_preflipped(filename, size, size, buffer);
676         }
677
678         envmap = false;
679         glDrawBuffer  (GL_BACK);
680         glReadBuffer  (GL_BACK);
681
682         Mem_Free(buffer);
683
684         // cause refdef to be fixed
685 //      vid.recalc_refdef = 1;
686 }
687
688 //=============================================================================
689
690
691 /*
692 ===============
693 SCR_BeginLoadingPlaque
694
695 ================
696 */
697 /*
698 void SCR_BeginLoadingPlaque (void)
699 {
700         S_StopAllSounds (true);
701
702 //      if (cls.state != ca_connected)
703 //              return;
704 //      if (cls.signon != SIGNONS)
705 //              return;
706
707 // redraw with no console and the loading plaque
708 //      Con_ClearNotify ();
709 //      scr_centertime_off = 0;
710 //      scr_con_current = 0;
711
712         scr_drawloading = true;
713         SCR_UpdateScreen ();
714
715 //      scr_disabled_for_loading = true;
716 //      scr_disabled_time = realtime;
717 }
718 */
719
720 /*
721 ===============
722 SCR_EndLoadingPlaque
723
724 ================
725 */
726 /*
727 void SCR_EndLoadingPlaque (void)
728 {
729 //      scr_disabled_for_loading = false;
730         scr_drawloading = false;
731         Con_ClearNotify ();
732 }
733 */
734
735 //=============================================================================
736
737 char    *scr_notifystring;
738
739 void SCR_DrawNotifyString (void)
740 {
741         char    *start;
742         int             l;
743         int             x, y;
744
745         start = scr_notifystring;
746
747         y = vid.conheight*0.35;
748
749         do      
750         {
751         // scan the width of the line
752                 for (l=0 ; l<40 ; l++)
753                         if (start[l] == '\n' || !start[l])
754                                 break;
755                 x = (vid.conwidth - l*8)/2;
756                 // LordHavoc: speedup
757 //              for (j=0 ; j<l ; j++, x+=8)
758 //                      Draw_Character (x, y, start[j]);
759                 Draw_String (x, y, start, l);
760
761                 y += 8;
762
763                 while (*start && *start != '\n')
764                         start++;
765
766                 if (!*start)
767                         break;
768                 start++;                // skip the \n
769         } while (1);
770 }
771
772 //=============================================================================
773
774 void DrawCrosshair(int num);
775 void GL_Set2D (void);
776
777 void GL_BrightenScreen(void)
778 {
779         float f;
780
781         if (r_brightness.value < 0.1f)
782                 Cvar_SetValue("r_brightness", 0.1f);
783         if (r_brightness.value > 5.0f)
784                 Cvar_SetValue("r_brightness", 5.0f);
785
786         if (r_contrast.value < 0.2f)
787                 Cvar_SetValue("r_contrast", 0.2f);
788         if (r_contrast.value > 1.0f)
789                 Cvar_SetValue("r_contrast", 1.0f);
790
791         if (!(lighthalf && !hardwaregammasupported) && r_brightness.value < 1.01f && r_contrast.value > 0.99f)
792                 return;
793
794         if (!r_render.integer)
795                 return;
796
797         glDisable(GL_TEXTURE_2D);
798         CHECKGLERROR
799         glEnable(GL_BLEND);
800         CHECKGLERROR
801         f = r_brightness.value;
802         // only apply lighthalf using software color correction if hardware is not available (speed reasons)
803         if (lighthalf && !hardwaregammasupported)
804                 f *= 2;
805         if (f >= 1.01f)
806         {
807                 glBlendFunc (GL_DST_COLOR, GL_ONE);
808                 CHECKGLERROR
809                 glBegin (GL_TRIANGLES);
810                 while (f >= 1.01f)
811                 {
812                         if (f >= 2)
813                                 glColor3f (1, 1, 1);
814                         else
815                                 glColor3f (f-1, f-1, f-1);
816                         glVertex2f (-5000, -5000);
817                         glVertex2f (10000, -5000);
818                         glVertex2f (-5000, 10000);
819                         f *= 0.5;
820                 }
821                 glEnd ();
822                 CHECKGLERROR
823         }
824         if (r_contrast.value <= 0.99f)
825         {
826                 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
827                 CHECKGLERROR
828                 if (lighthalf && hardwaregammasupported)
829                         glColor4f (0.5, 0.5, 0.5, 1 - r_contrast.value);
830                 else
831                         glColor4f (1, 1, 1, 1 - r_contrast.value);
832                 CHECKGLERROR
833                 glBegin (GL_TRIANGLES);
834                 glVertex2f (-5000, -5000);
835                 glVertex2f (10000, -5000);
836                 glVertex2f (-5000, 10000);
837                 glEnd ();
838                 CHECKGLERROR
839         }
840         glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
841         CHECKGLERROR
842
843         glEnable (GL_CULL_FACE);
844         CHECKGLERROR
845         glEnable (GL_DEPTH_TEST);
846         CHECKGLERROR
847         glDisable(GL_BLEND);
848         CHECKGLERROR
849         glEnable(GL_TEXTURE_2D);
850         CHECKGLERROR
851 }
852
853 /*
854 ==================
855 SCR_UpdateScreen
856
857 This is called every frame, and can also be called explicitly to flush
858 text to the screen.
859
860 LordHavoc: due to my rewrite of R_WorldNode, it no longer takes 256k of stack space :)
861 ==================
862 */
863 void GL_Finish(void);
864 void R_Clip_DisplayBuffer(void);
865 void SCR_UpdateScreen (void)
866 {
867         double  time1 = 0, time2;
868
869         if (r_speeds.integer)
870                 time1 = Sys_DoubleTime ();
871
872         VID_UpdateGamma(false);
873
874         if (scr_disabled_for_loading)
875         {
876                 /*
877                 if (realtime - scr_disabled_time > 60)
878                 {
879                         scr_disabled_for_loading = false;
880                         Con_Printf ("load failed.\n");
881                 }
882                 else
883                 */
884                         return;
885         }
886
887         if (!scr_initialized || !con_initialized)
888                 return;                         // not initialized yet
889
890
891         GL_BeginRendering (&vid.realx, &vid.realy, &vid.realwidth, &vid.realheight);
892
893         if (gl_combine.integer && !gl_combine_extension)
894                 Cvar_SetValue("gl_combine", 0);
895
896         lighthalf = gl_lightmode.integer;
897
898         lightscalebit = 0;
899         if (lighthalf)
900                 lightscalebit += 1;
901
902         if (gl_combine.integer && r_multitexture.integer)
903                 lightscalebit += 2;
904
905         lightscale = 1.0f / (float) (1 << lightscalebit);
906
907         //
908         // determine size of refresh window
909         //
910         if (oldfov != scr_fov.value)
911         {
912                 oldfov = scr_fov.value;
913 //              vid.recalc_refdef = true;
914         }
915
916         if (oldscreensize != scr_viewsize.value)
917         {
918                 oldscreensize = scr_viewsize.value;
919 //              vid.recalc_refdef = true;
920         }
921
922 //      if (vid.recalc_refdef)
923                 SCR_CalcRefdef();
924
925         if (r_render.integer)
926         {
927                 glClearColor(0,0,0,0);
928                 CHECKGLERROR
929                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: clear the screen (around the view as well)
930                 CHECKGLERROR
931         }
932
933         if (gl_dither.integer)
934                 glEnable(GL_DITHER);
935         else
936                 glDisable(GL_DITHER);
937         CHECKGLERROR
938
939 //
940 // do 3D refresh drawing, and then update the screen
941 //
942         SCR_SetUpToDrawConsole();
943
944         V_RenderView();
945
946         GL_Set2D();
947
948         R_Clip_DisplayBuffer();
949
950         SCR_DrawRam();
951         SCR_DrawNet();
952         SCR_DrawTurtle();
953         SCR_DrawPause();
954         SCR_CheckDrawCenterString();
955         Sbar_Draw();
956         SHOWLMP_drawall();
957
958         if (crosshair.integer)
959                 DrawCrosshair(crosshair.integer - 1);
960
961         if (cl.intermission == 1)
962                 Sbar_IntermissionOverlay();
963         else if (cl.intermission == 2)
964                 Sbar_FinaleOverlay();
965
966         SCR_DrawConsole();
967         M_Draw();
968
969         ui_draw();
970
971 //      if (scr_drawloading)
972 //              SCR_DrawLoading();
973
974         if (showfps.integer)
975         {
976                 static double currtime, frametimes[32];
977                 double newtime, total;
978                 char temp[32];
979                 int calc, count, i;
980                 static int framecycle = 0;
981                 newtime = Sys_DoubleTime();
982                 frametimes[framecycle] = newtime - currtime;
983                 framecycle++;
984                 framecycle &= 31;
985                 total = 0;
986                 count = 0;
987                 for (i = 0;i < 32;i++)
988                 {
989                         if (frametimes[i])
990                         {
991                                 total += frametimes[i];
992                                 count++;
993                                 // limit how far back we look
994                                 if (total >= 0.25)
995                                         break;
996                         }
997                 }
998                 if (showfps.integer == 1)
999                         calc = (int) ((count / total) + 0.5);
1000                 else // showfps 2, rapid update
1001                         calc = (int) ((1.0 / (newtime - currtime)) + 0.5);
1002                 sprintf(temp, "%4i fps", calc);
1003                 currtime = newtime;
1004                 Draw_String(vid.conwidth - (8*8), vid.conheight - sb_lines - 8, temp, 9999);
1005         }
1006
1007         if (r_speeds2.integer && r_speeds2_string[0])
1008         {
1009                 int i, j, lines, y;
1010                 lines = 1;
1011                 for (i = 0;r_speeds2_string[i];i++)
1012                         if (r_speeds2_string[i] == '\n')
1013                                 lines++;
1014                 y = vid.conheight - sb_lines - lines * 8 - 8;
1015                 i = j = 0;
1016                 while (r_speeds2_string[i])
1017                 {
1018                         j = i;
1019                         while (r_speeds2_string[i] && r_speeds2_string[i] != '\n')
1020                                 i++;
1021                         if (i - j > 0)
1022                                 Draw_String(0, y, r_speeds2_string + j, i - j);
1023                         if (r_speeds2_string[i] == '\n')
1024                                 i++;
1025                         y += 8;
1026                 }
1027                 // clear so it won't reprint without renderer being called again
1028                 r_speeds2_string[0] = 0;
1029         }
1030
1031         V_UpdateBlends();
1032
1033         GL_BrightenScreen();
1034
1035         GL_Finish();
1036
1037         if (r_speeds.integer)
1038         {
1039                 time2 = Sys_DoubleTime ();
1040                 Con_Printf ("%3i ms  %4i wpoly %4i epoly %6i meshtris %4i lightpoly %4i BSPnodes %4i BSPleafs %4i BSPfaces %4i models %4i bmodels %4i sprites %4i particles %3i dlights\n", (int)((time2-time1)*1000), c_brush_polys, c_alias_polys, c_meshtris, c_light_polys, c_nodes, c_leafs, c_faces, c_models, c_bmodels, c_sprites, c_particles, c_dlights);
1041         }
1042         GL_EndRendering ();
1043 }
1044
1045 // for profiling, this is separated
1046 void GL_Finish(void)
1047 {
1048         if (!r_render.integer)
1049                 return;
1050         glFinish ();
1051         CHECKGLERROR
1052 }
1053