]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_screen.c
rearranged r_speeds report a bit, and split up reporting of meshtris into normal...
[xonotic/darkplaces.git] / gl_screen.c
index 0e593950b467a474dcdc4ab275f31dabb3c0f0cf..9aa96b08b52ef0c077c0c0f78a9d66eab0868074 100644 (file)
@@ -8,7 +8,7 @@ of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 See the GNU General Public License for more details.
 
@@ -55,62 +55,49 @@ SlowPrint ()
 Screen_Update ();
 Con_Printf ();
 
-net 
+net
 turn off messages option
 
-the refresh is allways rendered, unless the console is full screen
+the refresh is always rendered, unless the console is full screen
 
 
 console is:
        notify lines
        half
        full
-       
-
-*/
 
 
-int                    glx, gly, glwidth, glheight;
-
-// only the refresh window will be updated unless these variables are flagged 
-int                    scr_copytop;
-int                    scr_copyeverything;
+*/
 
-float          scr_con_current;
-float          scr_conlines;           // lines of console to display
 
-float          oldscreensize, oldfov;
-cvar_t         scr_viewsize = {"viewsize","100", true};
-cvar_t         scr_fov = {"fov","90"}; // 10 - 170
-cvar_t         scr_conspeed = {"scr_conspeed","300"};
-cvar_t         scr_centertime = {"scr_centertime","2"};
-cvar_t         scr_showram = {"showram","1"};
-cvar_t         scr_showturtle = {"showturtle","0"};
-cvar_t         scr_showpause = {"showpause","1"};
-cvar_t         scr_printspeed = {"scr_printspeed","8"};
-cvar_t         showfps = {"showfps", "0", true};
-cvar_t         r_render = {"r_render", "1"};
+float  scr_con_current;
+float  scr_conlines;           // lines of console to display
 
-extern cvar_t  crosshair;
+float  oldscreensize, oldfov;
+cvar_t scr_viewsize = {CVAR_SAVE, "viewsize","100"};
+cvar_t scr_fov = {CVAR_SAVE, "fov","90"};      // 10 - 170
+cvar_t scr_conspeed = {CVAR_SAVE, "scr_conspeed","900"}; // LordHavoc: quake used 300
+cvar_t scr_centertime = {0, "scr_centertime","2"};
+cvar_t scr_showram = {CVAR_SAVE, "showram","1"};
+cvar_t scr_showturtle = {CVAR_SAVE, "showturtle","0"};
+cvar_t scr_showpause = {CVAR_SAVE, "showpause","1"};
+cvar_t scr_printspeed = {0, "scr_printspeed","8"};
+cvar_t r_render = {0, "r_render", "1"};
+cvar_t r_brightness = {CVAR_SAVE, "r_brightness", "1"}; // LordHavoc: a method of operating system independent color correction
+cvar_t r_contrast = {CVAR_SAVE, "r_contrast", "1"}; // LordHavoc: a method of operating system independent color correction
+cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1"}; // whether or not to use dithering
 
 qboolean       scr_initialized;                // ready to draw
 
-qpic_t         *scr_ram;
-qpic_t         *scr_net;
-qpic_t         *scr_turtle;
-
-int                    scr_fullupdate;
-
 int                    clearconsole;
 int                    clearnotify;
 
-extern int                     sb_lines;
-
-extern viddef_t        vid;                            // global video state
+int                    lightscalebit;
+float          lightscale;
 
 qboolean       scr_disabled_for_loading;
-qboolean       scr_drawloading;
-float          scr_disabled_time;
+//qboolean     scr_drawloading;
+//float                scr_disabled_time;
 
 void SCR_ScreenShot_f (void);
 
@@ -171,7 +158,7 @@ void SCR_DrawCenterString (void)
        start = scr_centerstring;
 
        if (scr_center_lines <= 4)
-               y = vid.height*0.35;
+               y = vid.conheight*0.35;
        else
                y = 48;
 
@@ -181,26 +168,17 @@ void SCR_DrawCenterString (void)
                for (l=0 ; l<40 ; l++)
                        if (start[l] == '\n' || !start[l])
                                break;
-               x = (vid.width - l*8)/2;
-               // LordHavoc: speedup
+               x = (vid.conwidth - l*8)/2;
                if (l > 0)
                {
                        if (remaining < l)
                                l = remaining;
-                       Draw_String(x, y, start, l);
+                       DrawQ_String(x, y, start, l, 8, 8, 1, 1, 1, 1, 0);
                        remaining -= l;
                        if (remaining <= 0)
                                return;
                }
-               /*
-               for (j=0 ; j<l ; j++, x+=8)
-               {
-                       Draw_Character (x, y, start[j]);        
-                       if (!remaining--)
-                               return;
-               }
-               */
-                       
+
                y += 8;
 
                while (*start && *start != '\n')
@@ -214,12 +192,11 @@ void SCR_DrawCenterString (void)
 
 void SCR_CheckDrawCenterString (void)
 {
-       scr_copytop = 1;
        if (scr_center_lines > scr_erase_lines)
                scr_erase_lines = scr_center_lines;
 
        scr_centertime_off -= host_frametime;
-       
+
        if (scr_centertime_off <= 0 && !cl.intermission)
                return;
        if (key_dest != key_game)
@@ -237,19 +214,8 @@ CalcFov
 */
 float CalcFov (float fov_x, float width, float height)
 {
-        float   a;
-        float   x;
-
-        if (fov_x < 1 || fov_x > 179)
-                Sys_Error ("Bad fov: %f", fov_x);
-
-        x = width/tan(fov_x/360*M_PI);
-
-        a = atan (height/x);
-
-        a = a*360/M_PI;
-
-        return a;
+       // calculate vision size and alter by aspect, then convert back to angle
+       return atan (height / (width / tan(fov_x/360*M_PI))) * 360 / M_PI;
 }
 
 /*
@@ -262,16 +228,12 @@ Internal use only
 */
 static void SCR_CalcRefdef (void)
 {
-       float           size;
-       int             h;
-       qboolean                full = false;
-
+       float size;
 
-       scr_fullupdate = 0;             // force a background redraw
-       vid.recalc_refdef = 0;
+//     vid.recalc_refdef = 0;
 
 //========================================
-       
+
 // bound viewsize
        if (scr_viewsize.value < 30)
                Cvar_Set ("viewsize","30");
@@ -284,57 +246,45 @@ static void SCR_CalcRefdef (void)
        if (scr_fov.value > 170)
                Cvar_Set ("fov","170");
 
-// intermission is always full screen  
+// intermission is always full screen
        if (cl.intermission)
-               size = 120;
-       else
-               size = scr_viewsize.value;
-
-       if (size >= 120)
-               sb_lines = 0;           // no status bar at all
-       else if (size >= 110)
-               sb_lines = 24;          // no inventory
-       else
-               sb_lines = 24+16+8;
-
-       if (scr_viewsize.value >= 100.0)
        {
-               full = true;
-               size = 100.0;
+               size = 1;
+               sb_lines = 0;
        }
        else
-               size = scr_viewsize.value;
-       if (cl.intermission)
        {
-               full = true;
-               size = 100;
-               sb_lines = 0;
+               if (scr_viewsize.value >= 120)
+                       sb_lines = 0;           // no status bar at all
+               else if (scr_viewsize.value >= 110)
+                       sb_lines = 24;          // no inventory
+               else
+                       sb_lines = 24+16+8;
+               size = scr_viewsize.value * (1.0 / 100.0);
        }
-       size /= 100.0;
 
-       // LordHavoc: always fullyscreen rendering
-       h = vid.height/* - sb_lines*/;
-
-       r_refdef.vrect.width = vid.width * size;
-       if (r_refdef.vrect.width < 96)
+       if (size >= 1)
        {
-               size = 96.0 / r_refdef.vrect.width;
-               r_refdef.vrect.width = 96;      // min for icons
+               r_refdef.width = vid.realwidth;
+               r_refdef.height = vid.realheight;
+               r_refdef.x = 0;
+               r_refdef.y = 0;
+       }
+       else
+       {
+               r_refdef.width = vid.realwidth * size;
+               r_refdef.height = vid.realheight * size;
+               r_refdef.x = (vid.realwidth - r_refdef.width)/2;
+               r_refdef.y = (vid.realheight - r_refdef.height)/2;
        }
-
-       r_refdef.vrect.height = vid.height * size;
-       //if (r_refdef.vrect.height > vid.height - sb_lines)
-       //      r_refdef.vrect.height = vid.height - sb_lines;
-       if (r_refdef.vrect.height > (int) vid.height)
-                       r_refdef.vrect.height = vid.height;
-       r_refdef.vrect.x = (vid.width - r_refdef.vrect.width)/2;
-       if (full)
-               r_refdef.vrect.y = 0;
-       else 
-               r_refdef.vrect.y = (h - r_refdef.vrect.height)/2;
 
        r_refdef.fov_x = scr_fov.value;
-       r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height);
+       r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.width, r_refdef.height);
+
+       r_refdef.width = bound(0, r_refdef.width, vid.realwidth);
+       r_refdef.height = bound(0, r_refdef.height, vid.realheight);
+       r_refdef.x = bound(0, r_refdef.x, vid.realwidth) + vid.realx;
+       r_refdef.y = bound(0, r_refdef.y, vid.realheight) + vid.realy;
 }
 
 
@@ -348,7 +298,6 @@ Keybinding command
 void SCR_SizeUp_f (void)
 {
        Cvar_SetValue ("viewsize",scr_viewsize.value+10);
-       vid.recalc_refdef = 1;
 }
 
 
@@ -362,19 +311,19 @@ Keybinding command
 void SCR_SizeDown_f (void)
 {
        Cvar_SetValue ("viewsize",scr_viewsize.value-10);
-       vid.recalc_refdef = 1;
 }
 
 //============================================================================
 
-void gl_screen_start()
+void gl_screen_start(void)
 {
-       scr_ram = Draw_PicFromWad ("ram");
-       scr_net = Draw_PicFromWad ("net");
-       scr_turtle = Draw_PicFromWad ("turtle");
 }
 
-void gl_screen_shutdown()
+void gl_screen_shutdown(void)
+{
+}
+
+void gl_screen_newmap(void)
 {
 }
 
@@ -383,9 +332,9 @@ void gl_screen_shutdown()
 SCR_Init
 ==================
 */
+static void R_Envmap_f (void);
 void GL_Screen_Init (void)
 {
-
        Cvar_RegisterVariable (&scr_fov);
        Cvar_RegisterVariable (&scr_viewsize);
        Cvar_RegisterVariable (&scr_conspeed);
@@ -394,22 +343,25 @@ void GL_Screen_Init (void)
        Cvar_RegisterVariable (&scr_showpause);
        Cvar_RegisterVariable (&scr_centertime);
        Cvar_RegisterVariable (&scr_printspeed);
-       Cvar_RegisterVariable (&showfps);
        Cvar_RegisterVariable (&r_render);
+       Cvar_RegisterVariable (&r_brightness);
+       Cvar_RegisterVariable (&r_contrast);
+       Cvar_RegisterVariable (&gl_dither);
 #ifdef NORENDER
-       r_render.value = 0;
+       Cvar_SetValue("r_render", 0);
 #endif
 
 //
 // register our commands
 //
        Cmd_AddCommand ("screenshot",SCR_ScreenShot_f);
+       Cmd_AddCommand ("envmap", R_Envmap_f);
        Cmd_AddCommand ("sizeup",SCR_SizeUp_f);
        Cmd_AddCommand ("sizedown",SCR_SizeDown_f);
 
        scr_initialized = true;
 
-       R_RegisterModule("GL_Screen", gl_screen_start, gl_screen_shutdown);
+       R_RegisterModule("GL_Screen", gl_screen_start, gl_screen_shutdown, gl_screen_newmap);
 }
 
 
@@ -421,13 +373,9 @@ SCR_DrawRam
 */
 void SCR_DrawRam (void)
 {
-       if (!scr_showram.value)
-               return;
-
-       if (!r_cache_thrash)
-               return;
-
-       Draw_Pic (32, 0, scr_ram);
+//     if (!scr_showram.integer)
+//             return;
+//     DrawQ_Pic (32, 0, "ram", 0, 0, 1, 1, 1, 1, 0);
 }
 
 /*
@@ -438,8 +386,11 @@ SCR_DrawTurtle
 void SCR_DrawTurtle (void)
 {
        static int      count;
-       
-       if (!scr_showturtle.value)
+
+       if (cls.state != ca_connected)
+               return;
+
+       if (!scr_showturtle.integer)
                return;
 
        if (host_frametime < 0.1)
@@ -452,7 +403,7 @@ void SCR_DrawTurtle (void)
        if (count < 3)
                return;
 
-       Draw_Pic (0, 0, scr_turtle);
+       DrawQ_Pic (0, 0, "turtle", 0, 0, 1, 1, 1, 1, 0);
 }
 
 /*
@@ -462,12 +413,14 @@ SCR_DrawNet
 */
 void SCR_DrawNet (void)
 {
+       if (cls.state != ca_connected)
+               return;
        if (realtime - cl.last_received_message < 0.3)
                return;
        if (cls.demoplayback)
                return;
 
-       Draw_Pic (64, 0, scr_net);
+       DrawQ_Pic (64, 0, "net", 0, 0, 1, 1, 1, 1, 0);
 }
 
 /*
@@ -477,17 +430,19 @@ DrawPause
 */
 void SCR_DrawPause (void)
 {
-       qpic_t  *pic;
+       cachepic_t      *pic;
 
-       if (!scr_showpause.value)               // turn off for screenshots
+       if (cls.state != ca_connected)
+               return;
+
+       if (!scr_showpause.integer)             // turn off for screenshots
                return;
 
        if (!cl.paused)
                return;
 
        pic = Draw_CachePic ("gfx/pause.lmp");
-       Draw_Pic ( (vid.width - pic->width)/2, 
-               (vid.height - 48 - pic->height)/2, pic);
+       DrawQ_Pic ((vid.conwidth - pic->width)/2, (vid.conheight - pic->height)/2, "gfx/pause.lmp", 0, 0, 1, 1, 1, 1, 0);
 }
 
 
@@ -497,17 +452,18 @@ void SCR_DrawPause (void)
 SCR_DrawLoading
 ==============
 */
+/*
 void SCR_DrawLoading (void)
 {
-       qpic_t  *pic;
+       cachepic_t      *pic;
 
        if (!scr_drawloading)
                return;
-               
+
        pic = Draw_CachePic ("gfx/loading.lmp");
-       Draw_Pic ( (vid.width - pic->width)/2, 
-               (vid.height - 48 - pic->height)/2, pic);
+       DrawQ_Pic ((vid.conwidth - pic->width)/2, (vid.conheight - pic->height)/2, "gfx/loading.lmp", 0, 0, 1, 1, 1, 1, 0);
 }
+*/
 
 
 
@@ -522,23 +478,20 @@ SCR_SetUpToDrawConsole
 void SCR_SetUpToDrawConsole (void)
 {
        Con_CheckResize ();
-       
-       //if (scr_drawloading)
-       //      return;         // never a console with loading plaque
 
 // decide on the height of the console
        con_forcedup = !cl.worldmodel || cls.signon != SIGNONS;
 
        if (con_forcedup)
        {
-               scr_conlines = vid.height;              // full screen
+               scr_conlines = vid.conheight;           // full screen
                scr_con_current = scr_conlines;
        }
        else if (key_dest == key_console)
-               scr_conlines = vid.height/2;    // half screen
+               scr_conlines = vid.conheight/2; // half screen
        else
                scr_conlines = 0;                               // none visible
-       
+
        if (scr_conlines < scr_con_current)
        {
                scr_con_current -= scr_conspeed.value*host_realframetime;
@@ -553,7 +506,7 @@ void SCR_SetUpToDrawConsole (void)
                        scr_con_current = scr_conlines;
        }
 }
-       
+
 /*
 ==================
 SCR_DrawConsole
@@ -563,8 +516,7 @@ void SCR_DrawConsole (void)
 {
        if (scr_con_current)
        {
-               scr_copyeverything = 1;
-               Con_DrawConsole (scr_con_current, true);
+               Con_DrawConsole (scr_con_current);
                clearconsole = 0;
        }
        else
@@ -575,54 +527,155 @@ void SCR_DrawConsole (void)
 }
 
 
-/* 
-============================================================================== 
-                                               SCREEN SHOTS 
-============================================================================== 
-*/ 
+/*
+==============================================================================
+
+                                               SCREEN SHOTS
+
+==============================================================================
+*/
 
 /*
-================== 
+==================
 SCR_ScreenShot_f
-================== 
+==================
 */
-void SCR_ScreenShot_f (void) 
+void SCR_ScreenShot_f (void)
 {
-       byte            *buffer;
-       char            filename[80]; 
+       byte            *buffer, gamma[256];
+       char            filename[80];
        char            checkname[MAX_OSPATH];
        int                     i;
-// 
-// find a file name to save it to 
-// 
+//
+// find a file name to save it to
+//
        strcpy(filename,"dp0000.tga");
-               
-       for (i=0 ; i<=9999 ; i++) 
-       { 
-               filename[2] = (i/1000)%10 + '0'; 
-               filename[3] = (i/ 100)%10 + '0'; 
-               filename[4] = (i/  10)%10 + '0'; 
-               filename[5] = (i/   1)%10 + '0'; 
+
+       for (i=0 ; i<=9999 ; i++)
+       {
+               filename[2] = (i/1000)%10 + '0';
+               filename[3] = (i/ 100)%10 + '0';
+               filename[4] = (i/  10)%10 + '0';
+               filename[5] = (i/   1)%10 + '0';
                sprintf (checkname, "%s/%s", com_gamedir, filename);
                if (Sys_FileTime(checkname) == -1)
                        break;  // file doesn't exist
-       } 
+       }
        if (i==10000)
        {
-               Con_Printf ("SCR_ScreenShot_f: Couldn't create a TGA file\n"); 
+               Con_Printf ("SCR_ScreenShot_f: Couldn't create a TGA file\n");
                return;
        }
 
-       buffer = qmalloc(glwidth*glheight*3);
-       glReadPixels (glx, gly, glwidth, glheight, GL_RGB, GL_UNSIGNED_BYTE, buffer); 
-       Image_WriteTGARGB_preflipped(filename, glwidth, glheight, buffer);
+       buffer = Mem_Alloc(tempmempool, vid.realwidth*vid.realheight*3);
+       glReadPixels (vid.realx, vid.realy, vid.realwidth, vid.realheight, GL_RGB, GL_UNSIGNED_BYTE, buffer);
+       CHECKGLERROR
+
+       // apply hardware gamma to the image
+       BuildGammaTable8((lighthalf && hardwaregammasupported) ? 2.0f : 1.0f, 1, 1, 0, gamma);
+       Image_GammaRemapRGB(buffer, buffer, vid.realwidth*vid.realheight, gamma, gamma, gamma);
 
-       qfree(buffer);
+       Image_WriteTGARGB_preflipped(filename, vid.realwidth, vid.realheight, buffer);
+
+       Mem_Free(buffer);
        Con_Printf ("Wrote %s\n", filename);
 }
 
+/*
+===============
+R_Envmap_f
+
+Grab six views for environment mapping tests
+===============
+*/
+float CalcFov (float fov_x, float width, float height);
+struct
+{
+       float angles[3];
+       char *name;
+}
+envmapinfo[6] =
+{
+       {{  0,   0, 0}, "ft"},
+       {{  0,  90, 0}, "rt"},
+       {{  0, 180, 0}, "bk"},
+       {{  0, 270, 0}, "lf"},
+       {{-90,  90, 0}, "up"},
+       {{ 90,  90, 0}, "dn"}
+};
+static void R_Envmap_f (void)
+{
+       int             i, size;
+       char    filename[256];
+       char    basename[256];
+       byte    *buffer, gamma[256];
+
+       if (Cmd_Argc() != 3)
+       {
+               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");
+               return;
+       }
+
+       if (!r_render.integer)
+               return;
+
+       strcpy(basename, Cmd_Argv(1));
+       size = atoi(Cmd_Argv(2));
+       if (size != 128 && size != 256 && size != 512 && size != 1024)
+       {
+               Con_Printf("envmap: size must be one of 128, 256, 512, or 1024\n");
+               return;
+       }
+       if (size > vid.realwidth || size > vid.realheight)
+       {
+               Con_Printf("envmap: your resolution is not big enough to render that size\n");
+               return;
+       }
+
+       buffer = Mem_Alloc(tempmempool, size*size*3);
+       if (buffer == NULL)
+       {
+               Con_Printf("envmap: unable to allocate memory for image\n");
+               return;
+       }
+
+       BuildGammaTable8((lighthalf && hardwaregammasupported) ? 2.0f : 1.0f, 1, 1, 0, gamma);
+
+//     glDrawBuffer  (GL_FRONT);
+//     glReadBuffer  (GL_FRONT);
+       glDrawBuffer  (GL_BACK);
+       glReadBuffer  (GL_BACK);
+       envmap = true;
+
+       r_refdef.x = 0;
+       r_refdef.y = 0;
+       r_refdef.width = size;
+       r_refdef.height = size;
+
+       r_refdef.fov_x = 90;
+       r_refdef.fov_y = 90;
+
+       for (i = 0;i < 6;i++)
+       {
+               VectorCopy(envmapinfo[i].angles, r_refdef.viewangles);
+               glClearColor(0,0,0,0);
+               glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: clear the screen (around the view as well)
+               R_RenderView ();
+               glReadPixels (0, 0, size, size, GL_RGB, GL_UNSIGNED_BYTE, buffer);
+               sprintf(filename, "env/%s%s.tga", basename, envmapinfo[i].name);
+               Image_GammaRemapRGB(buffer, buffer, size * size, gamma, gamma, gamma);
+               Image_WriteTGARGB_preflipped(filename, size, size, buffer);
+       }
+
+       envmap = false;
+       glDrawBuffer  (GL_BACK);
+       glReadBuffer  (GL_BACK);
+
+       Mem_Free(buffer);
+
+       // cause refdef to be fixed
+//     vid.recalc_refdef = 1;
+}
 
 //=============================================================================
 
@@ -633,29 +686,28 @@ SCR_BeginLoadingPlaque
 
 ================
 */
+/*
 void SCR_BeginLoadingPlaque (void)
 {
        S_StopAllSounds (true);
 
-       if (cls.state != ca_connected)
-               return;
-       if (cls.signon != SIGNONS)
-               return;
-       
+//     if (cls.state != ca_connected)
+//             return;
+//     if (cls.signon != SIGNONS)
+//             return;
+
 // redraw with no console and the loading plaque
-       Con_ClearNotify ();
-       scr_centertime_off = 0;
-       scr_con_current = 0;
+//     Con_ClearNotify ();
+//     scr_centertime_off = 0;
+//     scr_con_current = 0;
 
        scr_drawloading = true;
-       scr_fullupdate = 0;
        SCR_UpdateScreen ();
-       scr_drawloading = false;
 
-       scr_disabled_for_loading = true;
-       scr_disabled_time = realtime;
-       scr_fullupdate = 0;
+//     scr_disabled_for_loading = true;
+//     scr_disabled_time = realtime;
 }
+*/
 
 /*
 ===============
@@ -663,17 +715,18 @@ SCR_EndLoadingPlaque
 
 ================
 */
+/*
 void SCR_EndLoadingPlaque (void)
 {
-       scr_disabled_for_loading = false;
-       scr_fullupdate = 0;
+//     scr_disabled_for_loading = false;
+       scr_drawloading = false;
        Con_ClearNotify ();
 }
+*/
 
 //=============================================================================
 
 char   *scr_notifystring;
-qboolean       scr_drawdialog;
 
 void SCR_DrawNotifyString (void)
 {
@@ -683,7 +736,7 @@ void SCR_DrawNotifyString (void)
 
        start = scr_notifystring;
 
-       y = vid.height*0.35;
+       y = vid.conheight*0.35;
 
        do      
        {
@@ -691,12 +744,9 @@ void SCR_DrawNotifyString (void)
                for (l=0 ; l<40 ; l++)
                        if (start[l] == '\n' || !start[l])
                                break;
-               x = (vid.width - l*8)/2;
-               // LordHavoc: speedup
-//             for (j=0 ; j<l ; j++, x+=8)
-//                     Draw_Character (x, y, start[j]);        
-               Draw_String (x, y, start, l);
-                       
+               x = (vid.conwidth - l*8)/2;
+               DrawQ_String (x, y, start, l, 8, 8, 1, 1, 1, 1, 0);
+
                y += 8;
 
                while (*start && *start != '\n')
@@ -705,116 +755,119 @@ void SCR_DrawNotifyString (void)
                if (!*start)
                        break;
                start++;                // skip the \n
-       } while (1);
+       }
+       while (1);
 }
 
-/*
-==================
-SCR_ModalMessage
-
-Displays a text string in the center of the screen and waits for a Y or N
-keypress.  
-==================
-*/
-int SCR_ModalMessage (char *text)
-{
-       if (cls.state == ca_dedicated)
-               return true;
-
-       scr_notifystring = text;
-// draw a fresh screen
-       scr_fullupdate = 0;
-       scr_drawdialog = true;
-       SCR_UpdateScreen ();
-       scr_drawdialog = false;
-       
-       S_ClearBuffer ();               // so dma doesn't loop current sound
+//=============================================================================
 
-       do
-       {
-               key_count = -1;         // wait for a key down and up
-               Sys_SendKeyEvents ();
-       } while (key_lastpress != 'y' && key_lastpress != 'n' && key_lastpress != K_ESCAPE);
+void DrawCrosshair(int num);
 
-       scr_fullupdate = 0;
-       SCR_UpdateScreen ();
+char r_speeds_string[1024];
+int speedstringcount, r_timereport_active;
+double r_timereport_temp = 0, r_timereport_current = 0, r_timereport_start = 0;
 
-       return key_lastpress == 'y';
-}
+void R_TimeReport(char *desc)
+{
+       char tempbuf[256];
+       int length;
+       int t;
 
+       if (!r_timereport_active)
+               return;
 
-//=============================================================================
+       r_timereport_temp = r_timereport_current;
+       r_timereport_current = Sys_DoubleTime();
+       t = (int) ((r_timereport_current - r_timereport_temp) * 1000000.0);
 
-/*
-===============
-SCR_BringDownConsole
+       sprintf(tempbuf, "%8i %s", t, desc);
+       length = strlen(tempbuf);
+       while (length < 20)
+               tempbuf[length++] = ' ';
+       tempbuf[length] = 0;
+       if (speedstringcount + length > (vid.conwidth / 8))
+       {
+               strcat(r_speeds_string, "\n");
+               speedstringcount = 0;
+       }
+       // skip the space at the beginning if it's the first on the line
+       if (speedstringcount == 0)
+       {
+               strcat(r_speeds_string, tempbuf + 1);
+               speedstringcount = length - 1;
+       }
+       else
+       {
+               strcat(r_speeds_string, tempbuf);
+               speedstringcount += length;
+       }
+}
 
-Brings the console down and fades the blends back to normal
-================
-*/
-void SCR_BringDownConsole (void)
+void R_TimeReport_Start(void)
 {
-       int             i;
-       
-       scr_centertime_off = 0;
-       
-       for (i=0 ; i<20 && scr_conlines != scr_con_current ; i++)
-               SCR_UpdateScreen ();
-
-       cl.cshifts[0].percent = 0;              // no area contents blend on next frame
+       r_timereport_active = r_speeds.integer && cl.worldmodel && cls.state == ca_connected;
+       r_speeds_string[0] = 0;
+       if (r_timereport_active)
+       {
+               speedstringcount = 0;
+               AngleVectors (r_refdef.viewangles, vpn, NULL, NULL);
+               //sprintf(r_speeds_string, "org:'%c%6.2f %c%6.2f %c%6.2f' ang:'%c%3.0f %c%3.0f %c%3.0f' dir:'%c%2.3f %c%2.3f %c%2.3f'\n%6i walls %6i dlitwalls %7i modeltris %7i meshtris\nBSP: %6i faces %6i nodes %6i leafs\n%4i models %4i bmodels %4i sprites %5i particles %3i dlights\n",
+               //      r_refdef.vieworg[0] < 0 ? '-' : ' ', fabs(r_refdef.vieworg[0]), r_refdef.vieworg[1] < 0 ? '-' : ' ', fabs(r_refdef.vieworg[1]), r_refdef.vieworg[2] < 0 ? '-' : ' ', fabs(r_refdef.vieworg[2]),
+               //      r_refdef.viewangles[0] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[0]), r_refdef.viewangles[1] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[1]), r_refdef.viewangles[2] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[2]),
+               //      vpn[0] < 0 ? '-' : ' ', fabs(vpn[0]), vpn[1] < 0 ? '-' : ' ', fabs(vpn[1]), vpn[2] < 0 ? '-' : ' ', fabs(vpn[2]),
+               sprintf(r_speeds_string,
+                       "org:'%+8.2f %+8.2f %+8.2f' ang:'%+4.0f %+4.0f %+4.0f' dir:'%+2.3f %+2.3f %+2.3f'\n"
+                       "world:%6i faces%6i nodes%6i leafs%6i walls%6i dlitwalls\n"
+                       "%5i models%5i bmodels%5i sprites%6i particles%4i dlights\n"
+                       "%6i modeltris%6i transmeshs%6i transtris%6i meshs%6i meshtris\n",
+                       r_refdef.vieworg[0], r_refdef.vieworg[1], r_refdef.vieworg[2], r_refdef.viewangles[0], r_refdef.viewangles[1], r_refdef.viewangles[2], vpn[0], vpn[1], vpn[2],
+                       c_faces, c_nodes, c_leafs, c_brush_polys, c_light_polys,
+                       c_models, c_bmodels, c_sprites, c_particles, c_dlights,
+                       c_alias_polys, c_transmeshs, c_transtris, c_meshs, c_meshtris);
+
+               c_brush_polys = 0;
+               c_alias_polys = 0;
+               c_light_polys = 0;
+               c_faces = 0;
+               c_nodes = 0;
+               c_leafs = 0;
+               c_models = 0;
+               c_bmodels = 0;
+               c_sprites = 0;
+               c_particles = 0;
+       //      c_dlights = 0;
+
+               r_timereport_start = Sys_DoubleTime();
+       }
 }
 
-void DrawCrosshair(int num);
-void GL_Set2D (void);
-
-extern void SHOWLMP_drawall();
-extern cvar_t contrast;
-extern cvar_t brightness;
-extern cvar_t gl_lightmode;
-extern cvar_t r_speeds2;
-
-void GL_BrightenScreen()
+void R_TimeReport_End(void)
 {
-       float f;
-       if (!r_render.value)
-               return;
-       glDisable(GL_TEXTURE_2D);
-       glEnable(GL_BLEND);
-       f = brightness.value = bound(1.0f, brightness.value, 5.0f);
-       if (f >= 1.01f)
+       r_timereport_current = r_timereport_start;
+       R_TimeReport("total");
+
+       if (r_timereport_active)
        {
-               glBlendFunc (GL_DST_COLOR, GL_ONE);
-               glBegin (GL_TRIANGLES);
-               while (f >= 1.01f)
+               int i, j, lines, y;
+               lines = 1;
+               for (i = 0;r_speeds_string[i];i++)
+                       if (r_speeds_string[i] == '\n')
+                               lines++;
+               y = vid.conheight - sb_lines - lines * 8/* - 8*/;
+               i = j = 0;
+               DrawQ_Fill(0, y, vid.conwidth, lines * 8, 0, 0, 0, 0.5, 0);
+               while (r_speeds_string[i])
                {
-                       if (f >= 2)
-                               glColor3f (1, 1, 1);
-                       else
-                               glColor3f (f-1, f-1, f-1);
-                       glVertex2f (-5000, -5000);
-                       glVertex2f (10000, -5000);
-                       glVertex2f (-5000, 10000);
-                       f *= 0.5;
+                       j = i;
+                       while (r_speeds_string[i] && r_speeds_string[i] != '\n')
+                               i++;
+                       if (i - j > 0)
+                               DrawQ_String(0, y, r_speeds_string + j, i - j, 8, 8, 1, 1, 1, 1, 0);
+                       if (r_speeds_string[i] == '\n')
+                               i++;
+                       y += 8;
                }
-               glEnd ();
-       }
-       glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-       contrast.value = bound(0.2, contrast.value, 1.0);
-       if (contrast.value < 0.99f)
-       {
-               glBegin (GL_TRIANGLES);
-               glColor4f (1, 1, 1, 1-contrast.value);
-               glVertex2f (-5000, -5000);
-               glVertex2f (10000, -5000);
-               glVertex2f (-5000, 10000);
-               glEnd ();
        }
-
-       glEnable (GL_CULL_FACE);
-       glEnable (GL_DEPTH_TEST);
-       glDisable(GL_BLEND);
-       glEnable(GL_TEXTURE_2D);
 }
 
 /*
@@ -827,152 +880,90 @@ text to the screen.
 LordHavoc: due to my rewrite of R_WorldNode, it no longer takes 256k of stack space :)
 ==================
 */
-extern cvar_t gl_vertexarrays;
-extern qboolean gl_arrays;
-void GL_Finish();
 void SCR_UpdateScreen (void)
 {
-       double  time1 = 0, time2;
-
-       if (r_speeds.value)
-               time1 = Sys_FloatTime ();
-
-       if (!gl_arrays)
-               gl_vertexarrays.value = 0;
-
-       scr_copytop = 0;
-       scr_copyeverything = 0;
+       VID_UpdateGamma(false);
 
        if (scr_disabled_for_loading)
-       {
-               if (realtime - scr_disabled_time > 60)
-               {
-                       scr_disabled_for_loading = false;
-                       Con_Printf ("load failed.\n");
-               }
-               else
-                       return;
-       }
+               return;
 
        if (!scr_initialized || !con_initialized)
                return;                         // not initialized yet
 
+       //Mem_CheckSentinelsGlobal();
+       //R_TimeReport("memtest");
 
-       GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
-       
-       //
-       // determine size of refresh window
-       //
-       if (oldfov != scr_fov.value)
-       {
-               oldfov = scr_fov.value;
-               vid.recalc_refdef = true;
-       }
+       R_TimeReport("other");
 
-       if (oldscreensize != scr_viewsize.value)
-       {
-               oldscreensize = scr_viewsize.value;
-               vid.recalc_refdef = true;
-       }
+       glFinish ();
+       CHECKGLERROR
 
-       if (vid.recalc_refdef)
-               SCR_CalcRefdef ();
+       GL_EndRendering ();
 
-       if (r_render.value)
-       {
-               glClearColor(0,0,0,0);
-               glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: clear the screen (around the view as well)
-       }
+       R_TimeReport("finish");
 
-//
-// do 3D refresh drawing, and then update the screen
-//
-       SCR_SetUpToDrawConsole ();
+       GL_BeginRendering (&vid.realx, &vid.realy, &vid.realwidth, &vid.realheight);
 
-       V_RenderView ();
+       if (gl_combine.integer && !gl_combine_extension)
+               Cvar_SetValue("gl_combine", 0);
 
-       GL_Set2D ();
+       lighthalf = gl_lightmode.integer;
 
-       if (scr_drawdialog)
-       {
-               Sbar_Draw ();
-//             Draw_FadeScreen ();
-               SCR_DrawNotifyString ();
-               scr_copyeverything = true;
-       }
-       else if (scr_drawloading)
-       {
-               SCR_DrawLoading ();
-               Sbar_Draw ();
-       }
-       else if (cl.intermission == 1 && key_dest == key_game)
-       {
-               Sbar_IntermissionOverlay ();
-       }
-       else if (cl.intermission == 2 && key_dest == key_game)
-       {
-               Sbar_FinaleOverlay ();
-               SCR_CheckDrawCenterString ();
-       }
-       else
-       {
-               if (crosshair.value)
-                       DrawCrosshair(crosshair.value - 1);
-               
-               SCR_DrawRam ();
-               SCR_DrawNet ();
-               SCR_DrawTurtle ();
-               SCR_DrawPause ();
-               SCR_CheckDrawCenterString ();
-               Sbar_Draw ();
-               SHOWLMP_drawall();
-               SCR_DrawConsole ();     
-               M_Draw ();
-       }
+       lightscalebit = 0;
+       if (lighthalf)
+               lightscalebit += 1;
 
-       if (showfps.value)
-       {
-               static double currtime;
-               double newtime;
-               char temp[32];
-               int calc;
-               newtime = Sys_FloatTime();
-               calc = (int) ((1.0 / (newtime - currtime)) + 0.5);
-               sprintf(temp, "%4i fps", calc);
-               currtime = newtime;
-               Draw_String(vid.width - (8*8), vid.height - sb_lines - 8, temp, 9999);
-       }
+       if (gl_combine.integer && r_multitexture.integer)
+               lightscalebit += 2;
 
-       if (r_speeds2.value)
-       {
-               extern char r_speeds2_string1[81], r_speeds2_string2[81], r_speeds2_string3[81], r_speeds2_string4[81], r_speeds2_string5[81], r_speeds2_string6[81];
-               Draw_String(0, vid.height - sb_lines - 48, r_speeds2_string1, 80);
-               Draw_String(0, vid.height - sb_lines - 40, r_speeds2_string2, 80);
-               Draw_String(0, vid.height - sb_lines - 32, r_speeds2_string3, 80);
-               Draw_String(0, vid.height - sb_lines - 24, r_speeds2_string4, 80);
-               Draw_String(0, vid.height - sb_lines - 16, r_speeds2_string5, 80);
-               Draw_String(0, vid.height - sb_lines -  8, r_speeds2_string6, 80);
-       }
+       lightscale = 1.0f / (float) (1 << lightscalebit);
 
-       V_UpdateBlends ();
+       R_TimeReport("setup");
 
-       GL_BrightenScreen();
+       // determine size of refresh window
+       SCR_CalcRefdef();
 
-       GL_Finish();
+       R_TimeReport("calcrefdef");
 
-       if (r_speeds.value)
+       if (r_render.integer)
        {
-               time2 = Sys_FloatTime ();
-               Con_Printf ("%3i ms  %4i wpoly %4i epoly %4i transpoly %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, currenttranspoly, c_light_polys, c_nodes, c_leafs, c_faces, c_models, c_bmodels, c_sprites, c_particles, c_dlights);
+               glClearColor(0,0,0,0);
+               CHECKGLERROR
+               glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: clear the screen (around the view as well)
+               CHECKGLERROR
+               if (gl_dither.integer)
+                       glEnable(GL_DITHER);
+               else
+                       glDisable(GL_DITHER);
+               CHECKGLERROR
        }
-       GL_EndRendering ();
-}
 
-// for profiling, this is seperated
-void GL_Finish()
-{
-       if (!r_render.value)
-               return;
-       glFinish ();
-}
+       SCR_SetUpToDrawConsole();
+
+       R_TimeReport("clear");
+
+       if (scr_conlines < vid.conheight)
+               R_RenderView();
+
+       SCR_DrawRam();
+       SCR_DrawNet();
+       SCR_DrawTurtle();
+       SCR_DrawPause();
+       SCR_CheckDrawCenterString();
+       Sbar_Draw();
+       SHOWLMP_drawall();
 
+       SCR_DrawConsole();
+       M_Draw();
+
+       ui_draw();
+
+       R_TimeReport("2d");
+
+       R_TimeReport_End();
+
+       // draw 2D stuff
+       R_DrawQueue();
+
+       R_TimeReport_Start();
+}