a5e7d733b5caaf0337e5c6a7c7d66dcdc53280bb
[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 allways 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 int                     glx, gly, glwidth, glheight;
74
75 // only the refresh window will be updated unless these variables are flagged 
76 int                     scr_copytop;
77 int                     scr_copyeverything;
78
79 float           scr_con_current;
80 float           scr_conlines;           // lines of console to display
81
82 float           oldscreensize, oldfov;
83 cvar_t          scr_viewsize = {"viewsize","100", true};
84 cvar_t          scr_fov = {"fov","90"}; // 10 - 170
85 cvar_t          scr_conspeed = {"scr_conspeed","300"};
86 cvar_t          scr_centertime = {"scr_centertime","2"};
87 cvar_t          scr_showram = {"showram","1"};
88 cvar_t          scr_showturtle = {"showturtle","0"};
89 cvar_t          scr_showpause = {"showpause","1"};
90 cvar_t          scr_printspeed = {"scr_printspeed","8"};
91 cvar_t          showfps = {"showfps", "0", true};
92
93 extern  cvar_t  crosshair;
94
95 qboolean        scr_initialized;                // ready to draw
96
97 qpic_t          *scr_ram;
98 qpic_t          *scr_net;
99 qpic_t          *scr_turtle;
100
101 int                     scr_fullupdate;
102
103 int                     clearconsole;
104 int                     clearnotify;
105
106 extern int                     sb_lines;
107
108 extern viddef_t        vid;                            // global video state
109
110 qboolean        scr_disabled_for_loading;
111 qboolean        scr_drawloading;
112 float           scr_disabled_time;
113
114 void SCR_ScreenShot_f (void);
115
116 /*
117 ===============================================================================
118
119 CENTER PRINTING
120
121 ===============================================================================
122 */
123
124 char            scr_centerstring[1024];
125 float           scr_centertime_start;   // for slow victory printing
126 float           scr_centertime_off;
127 int                     scr_center_lines;
128 int                     scr_erase_lines;
129 int                     scr_erase_center;
130
131 /*
132 ==============
133 SCR_CenterPrint
134
135 Called for important messages that should stay in the center of the screen
136 for a few moments
137 ==============
138 */
139 void SCR_CenterPrint (char *str)
140 {
141         strncpy (scr_centerstring, str, sizeof(scr_centerstring)-1);
142         scr_centertime_off = scr_centertime.value;
143         scr_centertime_start = cl.time;
144
145 // count the number of lines for centering
146         scr_center_lines = 1;
147         while (*str)
148         {
149                 if (*str == '\n')
150                         scr_center_lines++;
151                 str++;
152         }
153 }
154
155
156 void SCR_DrawCenterString (void)
157 {
158         char    *start;
159         int             l;
160         int             x, y;
161         int             remaining;
162
163 // the finale prints the characters one at a time
164         if (cl.intermission)
165                 remaining = scr_printspeed.value * (cl.time - scr_centertime_start);
166         else
167                 remaining = 9999;
168
169         scr_erase_center = 0;
170         start = scr_centerstring;
171
172         if (scr_center_lines <= 4)
173                 y = vid.height*0.35;
174         else
175                 y = 48;
176
177         do      
178         {
179         // scan the width of the line
180                 for (l=0 ; l<40 ; l++)
181                         if (start[l] == '\n' || !start[l])
182                                 break;
183                 x = (vid.width - l*8)/2;
184                 // LordHavoc: speedup
185                 if (l > 0)
186                 {
187                         if (remaining < l)
188                                 l = remaining;
189                         Draw_String(x, y, start, l);
190                         remaining -= l;
191                         if (remaining <= 0)
192                                 return;
193                 }
194                 /*
195                 for (j=0 ; j<l ; j++, x+=8)
196                 {
197                         Draw_Character (x, y, start[j]);        
198                         if (!remaining--)
199                                 return;
200                 }
201                 */
202                         
203                 y += 8;
204
205                 while (*start && *start != '\n')
206                         start++;
207
208                 if (!*start)
209                         break;
210                 start++;                // skip the \n
211         } while (1);
212 }
213
214 void SCR_CheckDrawCenterString (void)
215 {
216         scr_copytop = 1;
217         if (scr_center_lines > scr_erase_lines)
218                 scr_erase_lines = scr_center_lines;
219
220         scr_centertime_off -= host_frametime;
221         
222         if (scr_centertime_off <= 0 && !cl.intermission)
223                 return;
224         if (key_dest != key_game)
225                 return;
226
227         SCR_DrawCenterString ();
228 }
229
230 //=============================================================================
231
232 /*
233 ====================
234 CalcFov
235 ====================
236 */
237 float CalcFov (float fov_x, float width, float height)
238 {
239         float   a;
240         float   x;
241
242         if (fov_x < 1 || fov_x > 179)
243                 Sys_Error ("Bad fov: %f", fov_x);
244
245         x = width/tan(fov_x/360*M_PI);
246
247         a = atan (height/x);
248
249         a = a*360/M_PI;
250
251         return a;
252 }
253
254 /*
255 =================
256 SCR_CalcRefdef
257
258 Must be called whenever vid changes
259 Internal use only
260 =================
261 */
262 static void SCR_CalcRefdef (void)
263 {
264         float           size;
265         int             h;
266         qboolean                full = false;
267
268
269         scr_fullupdate = 0;             // force a background redraw
270         vid.recalc_refdef = 0;
271
272 // force the status bar to redraw
273 //      Sbar_Changed ();
274
275 //========================================
276         
277 // bound viewsize
278         if (scr_viewsize.value < 30)
279                 Cvar_Set ("viewsize","30");
280         if (scr_viewsize.value > 120)
281                 Cvar_Set ("viewsize","120");
282
283 // bound field of view
284         if (scr_fov.value < 10)
285                 Cvar_Set ("fov","10");
286         if (scr_fov.value > 170)
287                 Cvar_Set ("fov","170");
288
289 // intermission is always full screen   
290         if (cl.intermission)
291                 size = 120;
292         else
293                 size = scr_viewsize.value;
294
295         if (size >= 120)
296                 sb_lines = 0;           // no status bar at all
297         else if (size >= 110)
298                 sb_lines = 24;          // no inventory
299         else
300                 sb_lines = 24+16+8;
301
302         if (scr_viewsize.value >= 100.0)
303         {
304                 full = true;
305                 size = 100.0;
306         }
307         else
308                 size = scr_viewsize.value;
309         if (cl.intermission)
310         {
311                 full = true;
312                 size = 100;
313                 sb_lines = 0;
314         }
315         size /= 100.0;
316
317         // LordHavoc: always fullyscreen rendering
318         h = vid.height/* - sb_lines*/;
319
320         r_refdef.vrect.width = vid.width * size;
321         if (r_refdef.vrect.width < 96)
322         {
323                 size = 96.0 / r_refdef.vrect.width;
324                 r_refdef.vrect.width = 96;      // min for icons
325         }
326
327         r_refdef.vrect.height = vid.height * size;
328         //if (r_refdef.vrect.height > vid.height - sb_lines)
329         //      r_refdef.vrect.height = vid.height - sb_lines;
330         if (r_refdef.vrect.height > (int) vid.height)
331                         r_refdef.vrect.height = vid.height;
332         r_refdef.vrect.x = (vid.width - r_refdef.vrect.width)/2;
333         if (full)
334                 r_refdef.vrect.y = 0;
335         else 
336                 r_refdef.vrect.y = (h - r_refdef.vrect.height)/2;
337
338         r_refdef.fov_x = scr_fov.value;
339         r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height);
340 }
341
342
343 /*
344 =================
345 SCR_SizeUp_f
346
347 Keybinding command
348 =================
349 */
350 void SCR_SizeUp_f (void)
351 {
352         Cvar_SetValue ("viewsize",scr_viewsize.value+10);
353         vid.recalc_refdef = 1;
354 }
355
356
357 /*
358 =================
359 SCR_SizeDown_f
360
361 Keybinding command
362 =================
363 */
364 void SCR_SizeDown_f (void)
365 {
366         Cvar_SetValue ("viewsize",scr_viewsize.value-10);
367         vid.recalc_refdef = 1;
368 }
369
370 //============================================================================
371
372 void gl_screen_start()
373 {
374         scr_ram = Draw_PicFromWad ("ram");
375         scr_net = Draw_PicFromWad ("net");
376         scr_turtle = Draw_PicFromWad ("turtle");
377 }
378
379 void gl_screen_shutdown()
380 {
381 }
382
383 /*
384 ==================
385 SCR_Init
386 ==================
387 */
388 void GL_Screen_Init (void)
389 {
390
391         Cvar_RegisterVariable (&scr_fov);
392         Cvar_RegisterVariable (&scr_viewsize);
393         Cvar_RegisterVariable (&scr_conspeed);
394         Cvar_RegisterVariable (&scr_showram);
395         Cvar_RegisterVariable (&scr_showturtle);
396         Cvar_RegisterVariable (&scr_showpause);
397         Cvar_RegisterVariable (&scr_centertime);
398         Cvar_RegisterVariable (&scr_printspeed);
399         Cvar_RegisterVariable (&showfps);
400
401 //
402 // register our commands
403 //
404         Cmd_AddCommand ("screenshot",SCR_ScreenShot_f);
405         Cmd_AddCommand ("sizeup",SCR_SizeUp_f);
406         Cmd_AddCommand ("sizedown",SCR_SizeDown_f);
407
408         scr_initialized = true;
409
410         R_RegisterModule("GL_Screen", gl_screen_start, gl_screen_shutdown);
411 }
412
413
414
415 /*
416 ==============
417 SCR_DrawRam
418 ==============
419 */
420 void SCR_DrawRam (void)
421 {
422         if (!scr_showram.value)
423                 return;
424
425         if (!r_cache_thrash)
426                 return;
427
428         Draw_Pic (32, 0, scr_ram);
429 }
430
431 /*
432 ==============
433 SCR_DrawTurtle
434 ==============
435 */
436 void SCR_DrawTurtle (void)
437 {
438         static int      count;
439         
440         if (!scr_showturtle.value)
441                 return;
442
443         if (host_frametime < 0.1)
444         {
445                 count = 0;
446                 return;
447         }
448
449         count++;
450         if (count < 3)
451                 return;
452
453         Draw_Pic (0, 0, scr_turtle);
454 }
455
456 /*
457 ==============
458 SCR_DrawNet
459 ==============
460 */
461 void SCR_DrawNet (void)
462 {
463         if (realtime - cl.last_received_message < 0.3)
464                 return;
465         if (cls.demoplayback)
466                 return;
467
468         Draw_Pic (64, 0, scr_net);
469 }
470
471 /*
472 ==============
473 DrawPause
474 ==============
475 */
476 void SCR_DrawPause (void)
477 {
478         qpic_t  *pic;
479
480         if (!scr_showpause.value)               // turn off for screenshots
481                 return;
482
483         if (!cl.paused)
484                 return;
485
486         pic = Draw_CachePic ("gfx/pause.lmp");
487         Draw_Pic ( (vid.width - pic->width)/2, 
488                 (vid.height - 48 - pic->height)/2, pic);
489 }
490
491
492
493 /*
494 ==============
495 SCR_DrawLoading
496 ==============
497 */
498 void SCR_DrawLoading (void)
499 {
500         qpic_t  *pic;
501
502         if (!scr_drawloading)
503                 return;
504                 
505         pic = Draw_CachePic ("gfx/loading.lmp");
506         Draw_Pic ( (vid.width - pic->width)/2, 
507                 (vid.height - 48 - pic->height)/2, pic);
508 }
509
510
511
512 //=============================================================================
513
514
515 /*
516 ==================
517 SCR_SetUpToDrawConsole
518 ==================
519 */
520 void SCR_SetUpToDrawConsole (void)
521 {
522         Con_CheckResize ();
523         
524         //if (scr_drawloading)
525         //      return;         // never a console with loading plaque
526
527 // decide on the height of the console
528         con_forcedup = !cl.worldmodel || cls.signon != SIGNONS;
529
530         if (con_forcedup)
531         {
532                 scr_conlines = vid.height;              // full screen
533                 scr_con_current = scr_conlines;
534         }
535         else if (key_dest == key_console)
536                 scr_conlines = vid.height/2;    // half screen
537         else
538                 scr_conlines = 0;                               // none visible
539         
540         if (scr_conlines < scr_con_current)
541         {
542                 scr_con_current -= scr_conspeed.value*host_frametime;
543                 if (scr_conlines > scr_con_current)
544                         scr_con_current = scr_conlines;
545
546         }
547         else if (scr_conlines > scr_con_current)
548         {
549                 scr_con_current += scr_conspeed.value*host_frametime;
550                 if (scr_conlines < scr_con_current)
551                         scr_con_current = scr_conlines;
552         }
553 }
554         
555 /*
556 ==================
557 SCR_DrawConsole
558 ==================
559 */
560 void SCR_DrawConsole (void)
561 {
562         if (scr_con_current)
563         {
564                 scr_copyeverything = 1;
565                 Con_DrawConsole (scr_con_current, true);
566                 clearconsole = 0;
567         }
568         else
569         {
570                 if (key_dest == key_game || key_dest == key_message)
571                         Con_DrawNotify ();      // only draw notify in game
572         }
573 }
574
575
576 /* 
577 ============================================================================== 
578  
579                                                 SCREEN SHOTS 
580  
581 ============================================================================== 
582 */ 
583
584 typedef struct _TargaHeader {
585         unsigned char   id_length, colormap_type, image_type;
586         unsigned short  colormap_index, colormap_length;
587         unsigned char   colormap_size;
588         unsigned short  x_origin, y_origin, width, height;
589         unsigned char   pixel_size, attributes;
590 } TargaHeader;
591
592
593 /* 
594 ================== 
595 SCR_ScreenShot_f
596 ================== 
597 */  
598 void SCR_ScreenShot_f (void) 
599 {
600         byte            *buffer;
601         char            pcxname[80]; 
602         char            checkname[MAX_OSPATH];
603         int                     i, c, temp;
604 // 
605 // find a file name to save it to 
606 // 
607         strcpy(pcxname,"dp0000.tga");
608                 
609         for (i=0 ; i<=9999 ; i++) 
610         { 
611                 pcxname[2] = (i/1000)%10 + '0'; 
612                 pcxname[3] = (i/ 100)%10 + '0'; 
613                 pcxname[4] = (i/  10)%10 + '0'; 
614                 pcxname[5] = (i/   1)%10 + '0'; 
615                 sprintf (checkname, "%s/%s", com_gamedir, pcxname);
616                 if (Sys_FileTime(checkname) == -1)
617                         break;  // file doesn't exist
618         } 
619         if (i==10000)
620         {
621                 Con_Printf ("SCR_ScreenShot_f: Couldn't create a TGA file\n"); 
622                 return;
623         }
624
625
626         buffer = malloc(glwidth*glheight*3 + 18);
627         memset (buffer, 0, 18);
628         buffer[2] = 2;          // uncompressed type
629         buffer[12] = glwidth&255;
630         buffer[13] = glwidth>>8;
631         buffer[14] = glheight&255;
632         buffer[15] = glheight>>8;
633         buffer[16] = 24;        // pixel size
634
635         glReadPixels (glx, gly, glwidth, glheight, GL_RGB, GL_UNSIGNED_BYTE, buffer+18 ); 
636
637         // swap rgb to bgr
638         c = 18+glwidth*glheight*3;
639         for (i=18 ; i<c ; i+=3)
640         {
641                 temp = buffer[i];
642                 buffer[i] = buffer[i+2];
643                 buffer[i+2] = temp;
644         }
645         COM_WriteFile (pcxname, buffer, glwidth*glheight*3 + 18 );
646
647         free (buffer);
648         Con_Printf ("Wrote %s\n", pcxname);
649
650
651
652 //=============================================================================
653
654
655 /*
656 ===============
657 SCR_BeginLoadingPlaque
658
659 ================
660 */
661 void SCR_BeginLoadingPlaque (void)
662 {
663         S_StopAllSounds (true);
664
665         if (cls.state != ca_connected)
666                 return;
667         if (cls.signon != SIGNONS)
668                 return;
669         
670 // redraw with no console and the loading plaque
671         Con_ClearNotify ();
672         scr_centertime_off = 0;
673         scr_con_current = 0;
674
675         scr_drawloading = true;
676         scr_fullupdate = 0;
677 //      Sbar_Changed ();
678         SCR_UpdateScreen ();
679         scr_drawloading = false;
680
681         scr_disabled_for_loading = true;
682         scr_disabled_time = realtime;
683         scr_fullupdate = 0;
684 }
685
686 /*
687 ===============
688 SCR_EndLoadingPlaque
689
690 ================
691 */
692 void SCR_EndLoadingPlaque (void)
693 {
694         scr_disabled_for_loading = false;
695         scr_fullupdate = 0;
696         Con_ClearNotify ();
697 }
698
699 //=============================================================================
700
701 char    *scr_notifystring;
702 qboolean        scr_drawdialog;
703
704 void SCR_DrawNotifyString (void)
705 {
706         char    *start;
707         int             l;
708         int             x, y;
709
710         start = scr_notifystring;
711
712         y = vid.height*0.35;
713
714         do      
715         {
716         // scan the width of the line
717                 for (l=0 ; l<40 ; l++)
718                         if (start[l] == '\n' || !start[l])
719                                 break;
720                 x = (vid.width - l*8)/2;
721                 // LordHavoc: speedup
722 //              for (j=0 ; j<l ; j++, x+=8)
723 //                      Draw_Character (x, y, start[j]);        
724                 Draw_String (x, y, start, l);
725                         
726                 y += 8;
727
728                 while (*start && *start != '\n')
729                         start++;
730
731                 if (!*start)
732                         break;
733                 start++;                // skip the \n
734         } while (1);
735 }
736
737 /*
738 ==================
739 SCR_ModalMessage
740
741 Displays a text string in the center of the screen and waits for a Y or N
742 keypress.  
743 ==================
744 */
745 int SCR_ModalMessage (char *text)
746 {
747         if (cls.state == ca_dedicated)
748                 return true;
749
750         scr_notifystring = text;
751  
752 // draw a fresh screen
753         scr_fullupdate = 0;
754         scr_drawdialog = true;
755         SCR_UpdateScreen ();
756         scr_drawdialog = false;
757         
758         S_ClearBuffer ();               // so dma doesn't loop current sound
759
760         do
761         {
762                 key_count = -1;         // wait for a key down and up
763                 Sys_SendKeyEvents ();
764         } while (key_lastpress != 'y' && key_lastpress != 'n' && key_lastpress != K_ESCAPE);
765
766         scr_fullupdate = 0;
767         SCR_UpdateScreen ();
768
769         return key_lastpress == 'y';
770 }
771
772
773 //=============================================================================
774
775 /*
776 ===============
777 SCR_BringDownConsole
778
779 Brings the console down and fades the palettes back to normal
780 ================
781 */
782 void SCR_BringDownConsole (void)
783 {
784         int             i;
785         
786         scr_centertime_off = 0;
787         
788         for (i=0 ; i<20 && scr_conlines != scr_con_current ; i++)
789                 SCR_UpdateScreen ();
790
791         cl.cshifts[0].percent = 0;              // no area contents palette on next frame
792 }
793
794 void DrawCrosshair(int num);
795 void GL_Set2D (void);
796
797 extern void SHOWLMP_drawall();
798 extern cvar_t contrast;
799 extern cvar_t brightness;
800 extern cvar_t gl_lightmode;
801
802 void GL_BrightenScreen()
803 {
804         float f;
805         glDisable(GL_TEXTURE_2D);
806         glEnable(GL_BLEND);
807         f = brightness.value = bound(1.0f, brightness.value, 5.0f);
808         if (f >= 1.01f)
809         {
810                 glBlendFunc (GL_DST_COLOR, GL_ONE);
811                 glBegin (GL_TRIANGLES);
812                 while (f >= 1.01f)
813                 {
814                         if (f >= 2)
815                                 glColor3f (1, 1, 1);
816                         else
817                                 glColor3f (f-1, f-1, f-1);
818                         glVertex2f (-5000, -5000);
819                         glVertex2f (10000, -5000);
820                         glVertex2f (-5000, 10000);
821                         f *= 0.5;
822                 }
823                 glEnd ();
824         }
825         glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
826         contrast.value = bound(0.2, contrast.value, 1.0);
827         if (contrast.value < 0.99f)
828         {
829                 glBegin (GL_TRIANGLES);
830                 glColor4f (1, 1, 1, 1-contrast.value);
831                 glVertex2f (-5000, -5000);
832                 glVertex2f (10000, -5000);
833                 glVertex2f (-5000, 10000);
834                 glEnd ();
835         }
836
837         glEnable (GL_CULL_FACE);
838         glEnable (GL_DEPTH_TEST);
839         glDisable(GL_BLEND);
840         glEnable(GL_TEXTURE_2D);
841 }
842
843 /*
844 ==================
845 SCR_UpdateScreen
846
847 This is called every frame, and can also be called explicitly to flush
848 text to the screen.
849
850 LordHavoc: due to my rewrite of R_WorldNode, it no longer takes 256k of stack space :)
851 ==================
852 */
853 extern cvar_t gl_vertexarrays;
854 extern qboolean gl_arrays;
855 void GL_Finish();
856 void SCR_UpdateScreen (void)
857 {
858         double  time1 = 0, time2;
859
860         if (r_speeds.value)
861                 time1 = Sys_FloatTime ();
862
863         if (!gl_arrays)
864                 gl_vertexarrays.value = 0;
865
866         scr_copytop = 0;
867         scr_copyeverything = 0;
868
869         if (scr_disabled_for_loading)
870         {
871                 if (realtime - scr_disabled_time > 60)
872                 {
873                         scr_disabled_for_loading = false;
874                         Con_Printf ("load failed.\n");
875                 }
876                 else
877                         return;
878         }
879
880         if (!scr_initialized || !con_initialized)
881                 return;                         // not initialized yet
882
883
884         GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
885         
886         //
887         // determine size of refresh window
888         //
889         if (oldfov != scr_fov.value)
890         {
891                 oldfov = scr_fov.value;
892                 vid.recalc_refdef = true;
893         }
894
895         if (oldscreensize != scr_viewsize.value)
896         {
897                 oldscreensize = scr_viewsize.value;
898                 vid.recalc_refdef = true;
899         }
900
901         if (vid.recalc_refdef)
902                 SCR_CalcRefdef ();
903
904         glClearColor(0,0,0,0);
905         glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: clear the screen (around the view as well)
906
907 //
908 // do 3D refresh drawing, and then update the screen
909 //
910         SCR_SetUpToDrawConsole ();
911
912         V_RenderView ();
913
914         GL_Set2D ();
915
916         if (scr_drawdialog)
917         {
918                 Sbar_Draw ();
919 //              Draw_FadeScreen ();
920                 SCR_DrawNotifyString ();
921                 scr_copyeverything = true;
922         }
923         else if (scr_drawloading)
924         {
925                 SCR_DrawLoading ();
926                 Sbar_Draw ();
927         }
928         else if (cl.intermission == 1 && key_dest == key_game)
929         {
930                 Sbar_IntermissionOverlay ();
931         }
932         else if (cl.intermission == 2 && key_dest == key_game)
933         {
934                 Sbar_FinaleOverlay ();
935                 SCR_CheckDrawCenterString ();
936         }
937         else
938         {
939                 if (crosshair.value)
940                         DrawCrosshair(crosshair.value);
941                 
942                 SCR_DrawRam ();
943                 SCR_DrawNet ();
944                 SCR_DrawTurtle ();
945                 SCR_DrawPause ();
946                 SCR_CheckDrawCenterString ();
947                 Sbar_Draw ();
948                 SHOWLMP_drawall();
949                 SCR_DrawConsole ();     
950                 M_Draw ();
951         }
952
953         if (showfps.value)
954         {
955                 static double currtime;
956                 double newtime;
957                 char temp[32];
958                 int calc;
959                 newtime = Sys_FloatTime();
960                 calc = (int) (100.0 / (newtime - currtime));
961                 sprintf(temp, "% 4i.%02i fps", calc / 100, calc % 100);
962                 currtime = newtime;
963                 Draw_String(vid.width - (12*8), 0, temp, 9999);
964         }
965
966         V_UpdatePalette ();
967
968         GL_BrightenScreen();
969
970         GL_Finish();
971
972         if (r_speeds.value)
973         {
974                 time2 = Sys_FloatTime ();
975                 Con_Printf ("%3i ms  %4i wpoly %4i epoly %4i transpoly %4i lightpoly %4i BSPnodes %4i BSPleafs\n", (int)((time2-time1)*1000), c_brush_polys, c_alias_polys, currenttranspoly, c_light_polys, c_nodes, c_leafs);
976         }
977         GL_EndRendering ();
978 }
979
980 // for profiling, this is seperated
981 void GL_Finish()
982 {
983         glFinish ();
984 }
985