]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_screen.c
cleaned up a lot of particle rendering properties (mainly related to rain code),...
[xonotic/darkplaces.git] / gl_screen.c
index 56ba7f3abd390ca37c37c495867215b219c40166..dc542a1c23859592c466f8bf2a74535d195f24a7 100644 (file)
@@ -55,7 +55,7 @@ SlowPrint ()
 Screen_Update ();
 Con_Printf ();
 
 Screen_Update ();
 Con_Printf ();
 
-net 
+net
 turn off messages option
 
 the refresh is always rendered, unless the console is full screen
 turn off messages option
 
 the refresh is always rendered, unless the console is full screen
@@ -65,39 +65,37 @@ console is:
        notify lines
        half
        full
        notify lines
        half
        full
-       
 
 
-*/
 
 
+*/
 
 
-int            glx, gly, glwidth, glheight;
 
 float  scr_con_current;
 float  scr_conlines;           // lines of console to display
 
 float  oldscreensize, oldfov;
 
 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"};
-cvar_t r_brightness = {"r_brightness", "1", true}; // LordHavoc: a method of operating system independent color correction
-cvar_t r_contrast = {"r_contrast", "1", true}; // LordHavoc: a method of operating system independent color correction
+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 showfps = {CVAR_SAVE, "showfps", "0"};
+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
 
 
 qboolean       scr_initialized;                // ready to draw
 
-qpic_t         *scr_ram;
-qpic_t         *scr_net;
-qpic_t         *scr_turtle;
-
 int                    clearconsole;
 int                    clearnotify;
 
 int                    clearconsole;
 int                    clearnotify;
 
+int                    lightscalebit;
+float          lightscale;
+
 qboolean       scr_disabled_for_loading;
 //qboolean     scr_drawloading;
 //float                scr_disabled_time;
 qboolean       scr_disabled_for_loading;
 //qboolean     scr_drawloading;
 //float                scr_disabled_time;
@@ -161,7 +159,7 @@ void SCR_DrawCenterString (void)
        start = scr_centerstring;
 
        if (scr_center_lines <= 4)
        start = scr_centerstring;
 
        if (scr_center_lines <= 4)
-               y = vid.height*0.35;
+               y = vid.conheight*0.35;
        else
                y = 48;
 
        else
                y = 48;
 
@@ -171,7 +169,7 @@ void SCR_DrawCenterString (void)
                for (l=0 ; l<40 ; l++)
                        if (start[l] == '\n' || !start[l])
                                break;
                for (l=0 ; l<40 ; l++)
                        if (start[l] == '\n' || !start[l])
                                break;
-               x = (vid.width - l*8)/2;
+               x = (vid.conwidth - l*8)/2;
                // LordHavoc: speedup
                if (l > 0)
                {
                // LordHavoc: speedup
                if (l > 0)
                {
@@ -208,7 +206,7 @@ void SCR_CheckDrawCenterString (void)
                scr_erase_lines = scr_center_lines;
 
        scr_centertime_off -= host_frametime;
                scr_erase_lines = scr_center_lines;
 
        scr_centertime_off -= host_frametime;
-       
+
        if (scr_centertime_off <= 0 && !cl.intermission)
                return;
        if (key_dest != key_game)
        if (scr_centertime_off <= 0 && !cl.intermission)
                return;
        if (key_dest != key_game)
@@ -226,19 +224,8 @@ CalcFov
 */
 float CalcFov (float fov_x, float width, float height)
 {
 */
 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;
 }
 
 /*
 }
 
 /*
@@ -251,15 +238,12 @@ Internal use only
 */
 static void SCR_CalcRefdef (void)
 {
 */
 static void SCR_CalcRefdef (void)
 {
-       float           size;
-       int             h;
-       qboolean                full = false;
+       float size;
 
 
-
-       vid.recalc_refdef = 0;
+//     vid.recalc_refdef = 0;
 
 //========================================
 
 //========================================
-       
+
 // bound viewsize
        if (scr_viewsize.value < 30)
                Cvar_Set ("viewsize","30");
 // bound viewsize
        if (scr_viewsize.value < 30)
                Cvar_Set ("viewsize","30");
@@ -272,10 +256,9 @@ static void SCR_CalcRefdef (void)
        if (scr_fov.value > 170)
                Cvar_Set ("fov","170");
 
        if (scr_fov.value > 170)
                Cvar_Set ("fov","170");
 
-// intermission is always full screen  
+// intermission is always full screen
        if (cl.intermission)
        {
        if (cl.intermission)
        {
-               full = true;
                size = 1;
                sb_lines = 0;
        }
                size = 1;
                sb_lines = 0;
        }
@@ -287,39 +270,31 @@ static void SCR_CalcRefdef (void)
                        sb_lines = 24;          // no inventory
                else
                        sb_lines = 24+16+8;
                        sb_lines = 24;          // no inventory
                else
                        sb_lines = 24+16+8;
-
-               if (scr_viewsize.value >= 100.0)
-               {
-                       full = true;
-                       size = 1.0f;
-               }
-               else
-                       size = scr_viewsize.value * (1.0f / 100.0f);
+               size = scr_viewsize.value * (1.0 / 100.0);
        }
 
        }
 
-       // LordHavoc: always fullscreen 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_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;
 }
 
 
 }
 
 
@@ -333,7 +308,7 @@ Keybinding command
 void SCR_SizeUp_f (void)
 {
        Cvar_SetValue ("viewsize",scr_viewsize.value+10);
 void SCR_SizeUp_f (void)
 {
        Cvar_SetValue ("viewsize",scr_viewsize.value+10);
-       vid.recalc_refdef = 1;
+//     vid.recalc_refdef = 1;
 }
 
 
 }
 
 
@@ -347,16 +322,13 @@ Keybinding command
 void SCR_SizeDown_f (void)
 {
        Cvar_SetValue ("viewsize",scr_viewsize.value-10);
 void SCR_SizeDown_f (void)
 {
        Cvar_SetValue ("viewsize",scr_viewsize.value-10);
-       vid.recalc_refdef = 1;
+//     vid.recalc_refdef = 1;
 }
 
 //============================================================================
 
 void gl_screen_start(void)
 {
 }
 
 //============================================================================
 
 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)
 }
 
 void gl_screen_shutdown(void)
@@ -372,9 +344,9 @@ void gl_screen_newmap(void)
 SCR_Init
 ==================
 */
 SCR_Init
 ==================
 */
+static void R_Envmap_f (void);
 void GL_Screen_Init (void)
 {
 void GL_Screen_Init (void)
 {
-
        Cvar_RegisterVariable (&scr_fov);
        Cvar_RegisterVariable (&scr_viewsize);
        Cvar_RegisterVariable (&scr_conspeed);
        Cvar_RegisterVariable (&scr_fov);
        Cvar_RegisterVariable (&scr_viewsize);
        Cvar_RegisterVariable (&scr_conspeed);
@@ -387,14 +359,16 @@ void GL_Screen_Init (void)
        Cvar_RegisterVariable (&r_render);
        Cvar_RegisterVariable (&r_brightness);
        Cvar_RegisterVariable (&r_contrast);
        Cvar_RegisterVariable (&r_render);
        Cvar_RegisterVariable (&r_brightness);
        Cvar_RegisterVariable (&r_contrast);
+       Cvar_RegisterVariable (&gl_dither);
 #ifdef NORENDER
 #ifdef NORENDER
-       r_render.value = 0;
+       Cvar_SetValue("r_render", 0);
 #endif
 
 //
 // register our commands
 //
        Cmd_AddCommand ("screenshot",SCR_ScreenShot_f);
 #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);
 
        Cmd_AddCommand ("sizeup",SCR_SizeUp_f);
        Cmd_AddCommand ("sizedown",SCR_SizeDown_f);
 
@@ -412,13 +386,9 @@ SCR_DrawRam
 */
 void SCR_DrawRam (void)
 {
 */
 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;
+//     Draw_Pic (32, 0, Draw_CachePic("ram"));
 }
 
 /*
 }
 
 /*
@@ -429,11 +399,11 @@ SCR_DrawTurtle
 void SCR_DrawTurtle (void)
 {
        static int      count;
 void SCR_DrawTurtle (void)
 {
        static int      count;
-       
-       if (!scr_showturtle.value)
+
+       if (!scr_showturtle.integer)
                return;
 
                return;
 
-       if (cl.frametime < 0.1)
+       if (host_frametime < 0.1)
        {
                count = 0;
                return;
        {
                count = 0;
                return;
@@ -443,7 +413,7 @@ void SCR_DrawTurtle (void)
        if (count < 3)
                return;
 
        if (count < 3)
                return;
 
-       Draw_Pic (0, 0, scr_turtle);
+       Draw_Pic (0, 0, Draw_CachePic("turtle"));
 }
 
 /*
 }
 
 /*
@@ -458,7 +428,7 @@ void SCR_DrawNet (void)
        if (cls.demoplayback)
                return;
 
        if (cls.demoplayback)
                return;
 
-       Draw_Pic (64, 0, scr_net);
+       Draw_Pic (64, 0, Draw_CachePic("net"));
 }
 
 /*
 }
 
 /*
@@ -470,15 +440,14 @@ void SCR_DrawPause (void)
 {
        qpic_t  *pic;
 
 {
        qpic_t  *pic;
 
-       if (!scr_showpause.value)               // turn off for screenshots
+       if (!scr_showpause.integer)             // turn off for screenshots
                return;
 
        if (!cl.paused)
                return;
 
        pic = Draw_CachePic ("gfx/pause.lmp");
                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);
+       Draw_Pic ((vid.conwidth - pic->width)/2, (vid.conheight - pic->height)/2, pic);
 }
 
 
 }
 
 
@@ -497,8 +466,7 @@ void SCR_DrawLoading (void)
                return;
                
        pic = Draw_CachePic ("gfx/loading.lmp");
                return;
                
        pic = Draw_CachePic ("gfx/loading.lmp");
-       Draw_Pic ( (vid.width - pic->width)/2, 
-               (vid.height - 48 - pic->height)/2, pic);
+       Draw_Pic ((vid.conwidth - pic->width)/2, (vid.conheight - pic->height)/2, pic);
 }
 */
 
 }
 */
 
@@ -524,14 +492,14 @@ void SCR_SetUpToDrawConsole (void)
 
        if (con_forcedup)
        {
 
        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_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
        else
                scr_conlines = 0;                               // none visible
-       
+
        if (scr_conlines < scr_con_current)
        {
                scr_con_current -= scr_conspeed.value*host_realframetime;
        if (scr_conlines < scr_con_current)
        {
                scr_con_current -= scr_conspeed.value*host_realframetime;
@@ -546,7 +514,7 @@ void SCR_SetUpToDrawConsole (void)
                        scr_con_current = scr_conlines;
        }
 }
                        scr_con_current = scr_conlines;
        }
 }
-       
+
 /*
 ==================
 SCR_DrawConsole
 /*
 ==================
 SCR_DrawConsole
@@ -567,54 +535,155 @@ void SCR_DrawConsole (void)
 }
 
 
 }
 
 
-/* 
+/*
 ============================================================================== 
 ============================================================================== 
+
                                                SCREEN SHOTS 
                                                SCREEN SHOTS 
+
 ============================================================================== 
 */ 
 
 /*
 ============================================================================== 
 */ 
 
 /*
-================== 
+==================
 SCR_ScreenShot_f
 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;
        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");
        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'; 
+
+       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
                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)
        {
        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;
        }
 
                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);
+
+       Image_WriteTGARGB_preflipped(filename, vid.realwidth, vid.realheight, buffer);
 
 
-       qfree(buffer);
+       Mem_Free(buffer);
        Con_Printf ("Wrote %s\n", filename);
 }
 
        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;
+}
 
 //=============================================================================
 
 
 //=============================================================================
 
@@ -634,7 +703,7 @@ void SCR_BeginLoadingPlaque (void)
 //             return;
 //     if (cls.signon != SIGNONS)
 //             return;
 //             return;
 //     if (cls.signon != SIGNONS)
 //             return;
-       
+
 // redraw with no console and the loading plaque
 //     Con_ClearNotify ();
 //     scr_centertime_off = 0;
 // redraw with no console and the loading plaque
 //     Con_ClearNotify ();
 //     scr_centertime_off = 0;
@@ -675,7 +744,7 @@ void SCR_DrawNotifyString (void)
 
        start = scr_notifystring;
 
 
        start = scr_notifystring;
 
-       y = vid.height*0.35;
+       y = vid.conheight*0.35;
 
        do      
        {
 
        do      
        {
@@ -683,10 +752,10 @@ void SCR_DrawNotifyString (void)
                for (l=0 ; l<40 ; l++)
                        if (start[l] == '\n' || !start[l])
                                break;
                for (l=0 ; l<40 ; l++)
                        if (start[l] == '\n' || !start[l])
                                break;
-               x = (vid.width - l*8)/2;
+               x = (vid.conwidth - l*8)/2;
                // LordHavoc: speedup
 //             for (j=0 ; j<l ; j++, x+=8)
                // LordHavoc: speedup
 //             for (j=0 ; j<l ; j++, x+=8)
-//                     Draw_Character (x, y, start[j]);        
+//                     Draw_Character (x, y, start[j]);
                Draw_String (x, y, start, l);
 
                y += 8;
                Draw_String (x, y, start, l);
 
                y += 8;
@@ -722,11 +791,13 @@ void GL_BrightenScreen(void)
        if (!(lighthalf && !hardwaregammasupported) && r_brightness.value < 1.01f && r_contrast.value > 0.99f)
                return;
 
        if (!(lighthalf && !hardwaregammasupported) && r_brightness.value < 1.01f && r_contrast.value > 0.99f)
                return;
 
-       if (!r_render.value)
+       if (!r_render.integer)
                return;
 
        glDisable(GL_TEXTURE_2D);
                return;
 
        glDisable(GL_TEXTURE_2D);
+       CHECKGLERROR
        glEnable(GL_BLEND);
        glEnable(GL_BLEND);
+       CHECKGLERROR
        f = r_brightness.value;
        // only apply lighthalf using software color correction if hardware is not available (speed reasons)
        if (lighthalf && !hardwaregammasupported)
        f = r_brightness.value;
        // only apply lighthalf using software color correction if hardware is not available (speed reasons)
        if (lighthalf && !hardwaregammasupported)
@@ -734,6 +805,7 @@ void GL_BrightenScreen(void)
        if (f >= 1.01f)
        {
                glBlendFunc (GL_DST_COLOR, GL_ONE);
        if (f >= 1.01f)
        {
                glBlendFunc (GL_DST_COLOR, GL_ONE);
+               CHECKGLERROR
                glBegin (GL_TRIANGLES);
                while (f >= 1.01f)
                {
                glBegin (GL_TRIANGLES);
                while (f >= 1.01f)
                {
@@ -747,26 +819,88 @@ void GL_BrightenScreen(void)
                        f *= 0.5;
                }
                glEnd ();
                        f *= 0.5;
                }
                glEnd ();
+               CHECKGLERROR
        }
        if (r_contrast.value <= 0.99f)
        {
                glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        }
        if (r_contrast.value <= 0.99f)
        {
                glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+               CHECKGLERROR
                if (lighthalf && hardwaregammasupported)
                        glColor4f (0.5, 0.5, 0.5, 1 - r_contrast.value);
                else
                        glColor4f (1, 1, 1, 1 - r_contrast.value);
                if (lighthalf && hardwaregammasupported)
                        glColor4f (0.5, 0.5, 0.5, 1 - r_contrast.value);
                else
                        glColor4f (1, 1, 1, 1 - r_contrast.value);
+               CHECKGLERROR
                glBegin (GL_TRIANGLES);
                glVertex2f (-5000, -5000);
                glVertex2f (10000, -5000);
                glVertex2f (-5000, 10000);
                glEnd ();
                glBegin (GL_TRIANGLES);
                glVertex2f (-5000, -5000);
                glVertex2f (10000, -5000);
                glVertex2f (-5000, 10000);
                glEnd ();
+               CHECKGLERROR
        }
        glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        }
        glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+       CHECKGLERROR
 
        glEnable (GL_CULL_FACE);
 
        glEnable (GL_CULL_FACE);
+       CHECKGLERROR
        glEnable (GL_DEPTH_TEST);
        glEnable (GL_DEPTH_TEST);
+       CHECKGLERROR
        glDisable(GL_BLEND);
        glDisable(GL_BLEND);
+       CHECKGLERROR
        glEnable(GL_TEXTURE_2D);
        glEnable(GL_TEXTURE_2D);
+       CHECKGLERROR
+}
+
+char r_speeds2_string[1024];
+int speedstringcount, r_timereport_active;
+double r_timereport_temp = 0, r_timereport_current = 0, r_timereport_start = 0;
+
+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);
+
+       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_speeds2_string, "\n");
+               speedstringcount = 0;
+       }
+       // skip the space at the beginning if it's the first on the line
+       if (speedstringcount == 0)
+       {
+               strcat(r_speeds2_string, tempbuf + 1);
+               speedstringcount = length - 1;
+       }
+       else
+       {
+               strcat(r_speeds2_string, tempbuf);
+               speedstringcount += length;
+       }
+}
+
+void R_TimeReport_Start(void)
+{
+       r_timereport_active = r_speeds2.integer && cl.worldmodel && cls.state == ca_connected;
+       if (r_timereport_active)
+               r_timereport_start = Sys_DoubleTime();
+}
+
+void R_TimeReport_End(void)
+{
+       r_timereport_current = r_timereport_start;
+       R_TimeReport("total");
 }
 
 /*
 }
 
 /*
@@ -785,7 +919,7 @@ void SCR_UpdateScreen (void)
 {
        double  time1 = 0, time2;
 
 {
        double  time1 = 0, time2;
 
-       if (r_speeds.value)
+       if (r_speeds.integer)
                time1 = Sys_DoubleTime ();
 
        VID_UpdateGamma(false);
                time1 = Sys_DoubleTime ();
 
        VID_UpdateGamma(false);
@@ -806,40 +940,89 @@ void SCR_UpdateScreen (void)
        if (!scr_initialized || !con_initialized)
                return;                         // not initialized yet
 
        if (!scr_initialized || !con_initialized)
                return;                         // not initialized yet
 
+       r_speeds2_string[0] = 0;
+       if (r_speeds2.integer)
+       {
+               speedstringcount = 0;
+               sprintf(r_speeds2_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_origin[0] < 0 ? '-' : ' ', fabs(r_origin[0]), r_origin[1] < 0 ? '-' : ' ', fabs(r_origin[1]), r_origin[2] < 0 ? '-' : ' ', fabs(r_origin[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]),
+                       c_brush_polys, c_light_polys, c_alias_polys, c_meshtris,
+                       c_faces, c_nodes, c_leafs,
+                       c_models, c_bmodels, c_sprites, c_particles, c_dlights);
+               R_TimeReport_Start();
+       }
+
+       Mem_CheckSentinelsGlobal();
+       R_TimeReport("memtest");
+
+       GL_Finish();
+       GL_EndRendering ();
+
+       R_TimeReport("finish");
+
+       GL_BeginRendering (&vid.realx, &vid.realy, &vid.realwidth, &vid.realheight);
+
+       if (gl_combine.integer && !gl_combine_extension)
+               Cvar_SetValue("gl_combine", 0);
+
+       lighthalf = gl_lightmode.integer;
+
+       lightscalebit = 0;
+       if (lighthalf)
+               lightscalebit += 1;
+
+       if (gl_combine.integer && r_multitexture.integer)
+               lightscalebit += 2;
+
+       lightscale = 1.0f / (float) (1 << lightscalebit);
 
 
-       GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
-       
        //
        // determine size of refresh window
        //
        if (oldfov != scr_fov.value)
        {
                oldfov = scr_fov.value;
        //
        // determine size of refresh window
        //
        if (oldfov != scr_fov.value)
        {
                oldfov = scr_fov.value;
-               vid.recalc_refdef = true;
+//             vid.recalc_refdef = true;
        }
 
        if (oldscreensize != scr_viewsize.value)
        {
                oldscreensize = scr_viewsize.value;
        }
 
        if (oldscreensize != scr_viewsize.value)
        {
                oldscreensize = scr_viewsize.value;
-               vid.recalc_refdef = true;
+//             vid.recalc_refdef = true;
        }
 
        }
 
-       if (vid.recalc_refdef)
+//     if (vid.recalc_refdef)
                SCR_CalcRefdef();
 
                SCR_CalcRefdef();
 
-       if (r_render.value)
+       R_TimeReport("calcrefdef");
+
+       if (r_render.integer)
        {
                glClearColor(0,0,0,0);
        {
                glClearColor(0,0,0,0);
+               CHECKGLERROR
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: clear the screen (around the view as well)
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: clear the screen (around the view as well)
+               CHECKGLERROR
        }
 
        }
 
+       R_TimeReport("clear");
+
+       if (gl_dither.integer)
+               glEnable(GL_DITHER);
+       else
+               glDisable(GL_DITHER);
+       CHECKGLERROR
+
 //
 // do 3D refresh drawing, and then update the screen
 //
        SCR_SetUpToDrawConsole();
 
 //
 // do 3D refresh drawing, and then update the screen
 //
        SCR_SetUpToDrawConsole();
 
+       R_TimeReport("setupconsole");
+
        V_RenderView();
 
        V_RenderView();
 
+       V_UpdateBlends();
+
        GL_Set2D();
 
        R_Clip_DisplayBuffer();
        GL_Set2D();
 
        R_Clip_DisplayBuffer();
@@ -852,42 +1035,67 @@ void SCR_UpdateScreen (void)
        Sbar_Draw();
        SHOWLMP_drawall();
 
        Sbar_Draw();
        SHOWLMP_drawall();
 
-       if (crosshair.value)
-               DrawCrosshair(crosshair.value - 1);
+       if (crosshair.integer)
+               DrawCrosshair(crosshair.integer - 1);
 
        if (cl.intermission == 1)
                Sbar_IntermissionOverlay();
        else if (cl.intermission == 2)
                Sbar_FinaleOverlay();
 
 
        if (cl.intermission == 1)
                Sbar_IntermissionOverlay();
        else if (cl.intermission == 2)
                Sbar_FinaleOverlay();
 
-       SCR_DrawConsole();      
+       SCR_DrawConsole();
        M_Draw();
 
        M_Draw();
 
+       ui_draw();
+
 //     if (scr_drawloading)
 //             SCR_DrawLoading();
 
 //     if (scr_drawloading)
 //             SCR_DrawLoading();
 
-       if (showfps.value)
+       if (showfps.integer)
        {
        {
-               static double currtime;
-               double newtime;
+               static double currtime, frametimes[32];
+               double newtime, total;
                char temp[32];
                char temp[32];
-               int calc;
+               int calc, count, i;
+               static int framecycle = 0;
                newtime = Sys_DoubleTime();
                newtime = Sys_DoubleTime();
-               calc = (int) ((1.0 / (newtime - currtime)) + 0.5);
+               frametimes[framecycle] = newtime - currtime;
+               framecycle++;
+               framecycle &= 31;
+               total = 0;
+               count = 0;
+               for (i = 0;i < 32;i++)
+               {
+                       if (frametimes[i])
+                       {
+                               total += frametimes[i];
+                               count++;
+                               // limit how far back we look
+                               if (total >= 0.25)
+                                       break;
+                       }
+               }
+               if (showfps.integer == 1)
+                       calc = (int) ((count / total) + 0.5);
+               else // showfps 2, rapid update
+                       calc = (int) ((1.0 / (newtime - currtime)) + 0.5);
                sprintf(temp, "%4i fps", calc);
                currtime = newtime;
                sprintf(temp, "%4i fps", calc);
                currtime = newtime;
-               Draw_String(vid.width - (8*8), vid.height - sb_lines - 8, temp, 9999);
+               Draw_String(vid.conwidth - (8*8), vid.conheight - sb_lines - 8, temp, 9999);
        }
 
        }
 
-       // LordHavoc: only print info if renderer is being used
-       if (r_speeds2.value && cl.worldmodel != NULL)
+       R_TimeReport("2d");
+
+       R_TimeReport_End();
+
+       if (r_speeds2_string[0] && cls.state == ca_connected && cl.worldmodel)
        {
                int i, j, lines, y;
                lines = 1;
                for (i = 0;r_speeds2_string[i];i++)
                        if (r_speeds2_string[i] == '\n')
                                lines++;
        {
                int i, j, lines, y;
                lines = 1;
                for (i = 0;r_speeds2_string[i];i++)
                        if (r_speeds2_string[i] == '\n')
                                lines++;
-               y = vid.height - sb_lines - lines * 8 - 8;
+               y = vid.conheight - sb_lines - lines * 8 - 8;
                i = j = 0;
                while (r_speeds2_string[i])
                {
                i = j = 0;
                while (r_speeds2_string[i])
                {
@@ -902,25 +1110,21 @@ void SCR_UpdateScreen (void)
                }
        }
 
                }
        }
 
-       V_UpdateBlends();
-
        GL_BrightenScreen();
 
        GL_BrightenScreen();
 
-       GL_Finish();
-
-       if (r_speeds.value)
+       if (r_speeds.integer)
        {
                time2 = Sys_DoubleTime ();
        {
                time2 = Sys_DoubleTime ();
-               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);
+               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);
        }
        }
-       GL_EndRendering ();
 }
 
 // for profiling, this is separated
 void GL_Finish(void)
 {
 }
 
 // for profiling, this is separated
 void GL_Finish(void)
 {
-       if (!r_render.value)
+       if (!r_render.integer)
                return;
        glFinish ();
                return;
        glFinish ();
+       CHECKGLERROR
 }
 
 }