]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_screen.c
added coronas (glow) to dynamic lights
[xonotic/darkplaces.git] / gl_screen.c
index 2a0bfa531316d6aae5022557505ba967586e8472..6eaf808f9835abfc0b5e408d389490ef8900a7c3 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
 
 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.
 
 
 See the GNU General Public License for more details.
 
@@ -55,64 +55,49 @@ SlowPrint ()
 Screen_Update ();
 Con_Printf ();
 
 Screen_Update ();
 Con_Printf ();
 
-net 
+net
 turn off messages option
 
 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
 
 
 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         gl_triplebuffer = {"gl_triplebuffer", "1", true };
-cvar_t         showfps = {"showfps", "0", true};
+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
 
 
 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;
 
 int                    clearconsole;
 int                    clearnotify;
 
-extern int                     sb_lines;
-
-extern viddef_t        vid;                            // global video state
-
-vrect_t                scr_vrect;
+int                    lightscalebit;
+float          lightscale;
 
 qboolean       scr_disabled_for_loading;
 
 qboolean       scr_disabled_for_loading;
-qboolean       scr_drawloading;
-float          scr_disabled_time;
+//qboolean     scr_drawloading;
+//float                scr_disabled_time;
 
 void SCR_ScreenShot_f (void);
 
 
 void SCR_ScreenShot_f (void);
 
@@ -173,7 +158,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;
 
@@ -183,26 +168,17 @@ 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;
-               // LordHavoc: speedup
+               x = (vid.conwidth - l*8)/2;
                if (l > 0)
                {
                        if (remaining < l)
                                l = remaining;
                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;
                }
                        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')
                y += 8;
 
                while (*start && *start != '\n')
@@ -216,12 +192,11 @@ void SCR_DrawCenterString (void)
 
 void SCR_CheckDrawCenterString (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_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)
        if (scr_centertime_off <= 0 && !cl.intermission)
                return;
        if (key_dest != key_game)
@@ -239,19 +214,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;
 }
 
 /*
 }
 
 /*
@@ -264,19 +228,12 @@ Internal use only
 */
 static void SCR_CalcRefdef (void)
 {
 */
 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;
-
-// force the status bar to redraw
-//     Sbar_Changed ();
+//     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");
@@ -289,59 +246,45 @@ 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)
-               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
        }
        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_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);
 
 
-       scr_vrect = r_refdef.vrect;
+       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;
 }
 
 
 }
 
 
@@ -355,7 +298,6 @@ 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;
 }
 
 
 }
 
 
@@ -369,19 +311,30 @@ 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;
 }
 
 //============================================================================
 
 }
 
 //============================================================================
 
+void gl_screen_start(void)
+{
+}
+
+void gl_screen_shutdown(void)
+{
+}
+
+void gl_screen_newmap(void)
+{
+}
+
 /*
 ==================
 SCR_Init
 ==================
 */
 /*
 ==================
 SCR_Init
 ==================
 */
-void SCR_Init (void)
+static void R_Envmap_f (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);
@@ -390,21 +343,25 @@ void SCR_Init (void)
        Cvar_RegisterVariable (&scr_showpause);
        Cvar_RegisterVariable (&scr_centertime);
        Cvar_RegisterVariable (&scr_printspeed);
        Cvar_RegisterVariable (&scr_showpause);
        Cvar_RegisterVariable (&scr_centertime);
        Cvar_RegisterVariable (&scr_printspeed);
-       Cvar_RegisterVariable (&gl_triplebuffer);
-       Cvar_RegisterVariable (&showfps);
+       Cvar_RegisterVariable (&r_render);
+       Cvar_RegisterVariable (&r_brightness);
+       Cvar_RegisterVariable (&r_contrast);
+       Cvar_RegisterVariable (&gl_dither);
+#ifdef NORENDER
+       Cvar_SetValue("r_render", 0);
+#endif
 
 //
 // register our commands
 //
        Cmd_AddCommand ("screenshot",SCR_ScreenShot_f);
 
 //
 // 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);
 
-       scr_ram = Draw_PicFromWad ("ram");
-       scr_net = Draw_PicFromWad ("net");
-       scr_turtle = Draw_PicFromWad ("turtle");
-
        scr_initialized = true;
        scr_initialized = true;
+
+       R_RegisterModule("GL_Screen", gl_screen_start, gl_screen_shutdown, gl_screen_newmap);
 }
 
 
 }
 
 
@@ -416,13 +373,9 @@ SCR_DrawRam
 */
 void SCR_DrawRam (void)
 {
 */
 void SCR_DrawRam (void)
 {
-       if (!scr_showram.value)
-               return;
-
-       if (!r_cache_thrash)
-               return;
-
-       Draw_Pic (scr_vrect.x+32, scr_vrect.y, scr_ram);
+//     if (!scr_showram.integer)
+//             return;
+//     DrawQ_Pic (32, 0, "ram", 0, 0, 1, 1, 1, 1, 0);
 }
 
 /*
 }
 
 /*
@@ -433,8 +386,11 @@ SCR_DrawTurtle
 void SCR_DrawTurtle (void)
 {
        static int      count;
 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)
                return;
 
        if (host_frametime < 0.1)
@@ -447,7 +403,7 @@ void SCR_DrawTurtle (void)
        if (count < 3)
                return;
 
        if (count < 3)
                return;
 
-       Draw_Pic (scr_vrect.x, scr_vrect.y, scr_turtle);
+       DrawQ_Pic (0, 0, "turtle", 0, 0, 1, 1, 1, 1, 0);
 }
 
 /*
 }
 
 /*
@@ -457,12 +413,14 @@ SCR_DrawNet
 */
 void SCR_DrawNet (void)
 {
 */
 void SCR_DrawNet (void)
 {
+       if (cls.state != ca_connected)
+               return;
        if (realtime - cl.last_received_message < 0.3)
                return;
        if (cls.demoplayback)
                return;
 
        if (realtime - cl.last_received_message < 0.3)
                return;
        if (cls.demoplayback)
                return;
 
-       Draw_Pic (scr_vrect.x+64, scr_vrect.y, scr_net);
+       DrawQ_Pic (64, 0, "net", 0, 0, 1, 1, 1, 1, 0);
 }
 
 /*
 }
 
 /*
@@ -472,17 +430,19 @@ DrawPause
 */
 void SCR_DrawPause (void)
 {
 */
 void SCR_DrawPause (void)
 {
-       qpic_t  *pic;
+       cachepic_t      *pic;
+
+       if (cls.state != ca_connected)
+               return;
 
 
-       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);
+       DrawQ_Pic ((vid.conwidth - pic->width)/2, (vid.conheight - pic->height)/2, "gfx/pause.lmp", 0, 0, 1, 1, 1, 1, 0);
 }
 
 
 }
 
 
@@ -492,17 +452,18 @@ void SCR_DrawPause (void)
 SCR_DrawLoading
 ==============
 */
 SCR_DrawLoading
 ==============
 */
+/*
 void SCR_DrawLoading (void)
 {
 void SCR_DrawLoading (void)
 {
-       qpic_t  *pic;
+       cachepic_t      *pic;
 
        if (!scr_drawloading)
                return;
 
        if (!scr_drawloading)
                return;
-               
+
        pic = Draw_CachePic ("gfx/loading.lmp");
        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);
 }
 }
+*/
 
 
 
 
 
 
@@ -517,50 +478,35 @@ SCR_SetUpToDrawConsole
 void SCR_SetUpToDrawConsole (void)
 {
        Con_CheckResize ();
 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)
        {
 
 // 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_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)
        {
        if (scr_conlines < scr_con_current)
        {
-               scr_con_current -= scr_conspeed.value*host_frametime;
+               scr_con_current -= scr_conspeed.value*host_realframetime;
                if (scr_conlines > scr_con_current)
                        scr_con_current = scr_conlines;
 
        }
        else if (scr_conlines > scr_con_current)
        {
                if (scr_conlines > scr_con_current)
                        scr_con_current = scr_conlines;
 
        }
        else if (scr_conlines > scr_con_current)
        {
-               scr_con_current += scr_conspeed.value*host_frametime;
+               scr_con_current += scr_conspeed.value*host_realframetime;
                if (scr_conlines < scr_con_current)
                        scr_con_current = scr_conlines;
        }
                if (scr_conlines < scr_con_current)
                        scr_con_current = scr_conlines;
        }
-
-       /*
-       if (clearconsole++ < vid.numpages)
-       {
-               Sbar_Changed ();
-       }
-       else if (clearnotify++ < vid.numpages)
-       {
-       }
-       else
-               con_notifylines = 0;
-       */
 }
 }
-       
+
 /*
 ==================
 SCR_DrawConsole
 /*
 ==================
 SCR_DrawConsole
@@ -570,8 +516,7 @@ void SCR_DrawConsole (void)
 {
        if (scr_con_current)
        {
 {
        if (scr_con_current)
        {
-               scr_copyeverything = 1;
-               Con_DrawConsole (scr_con_current, true);
+               Con_DrawConsole (scr_con_current);
                clearconsole = 0;
        }
        else
                clearconsole = 0;
        }
        else
@@ -582,81 +527,155 @@ void SCR_DrawConsole (void)
 }
 
 
 }
 
 
-/* 
-============================================================================== 
-                                               SCREEN SHOTS 
-============================================================================== 
-*/ 
+/*
+==============================================================================
 
 
-typedef struct _TargaHeader {
-       unsigned char   id_length, colormap_type, image_type;
-       unsigned short  colormap_index, colormap_length;
-       unsigned char   colormap_size;
-       unsigned short  x_origin, y_origin, width, height;
-       unsigned char   pixel_size, attributes;
-} TargaHeader;
+                                               SCREEN SHOTS
 
 
+==============================================================================
+*/
 
 
-/* 
-================== 
+/*
+==================
 SCR_ScreenShot_f
 SCR_ScreenShot_f
-================== 
-*/  
-void SCR_ScreenShot_f (void) 
+==================
+*/
+void SCR_ScreenShot_f (void)
 {
 {
-       byte            *buffer;
-       char            pcxname[80]; 
+       byte            *buffer, gamma[256];
+       char            filename[80];
        char            checkname[MAX_OSPATH];
        char            checkname[MAX_OSPATH];
-       int                     i, c, temp;
-// 
-// find a file name to save it to 
-// 
-       strcpy(pcxname,"dp0000.tga");
-               
-       for (i=0 ; i<=9999 ; i++) 
-       { 
-               pcxname[2] = (i/1000)%10 + '0'; 
-               pcxname[3] = (i/ 100)%10 + '0'; 
-               pcxname[4] = (i/  10)%10 + '0'; 
-               pcxname[5] = (i/   1)%10 + '0'; 
-               sprintf (checkname, "%s/%s", com_gamedir, pcxname);
+       int                     i;
+//
+// 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';
+               sprintf (checkname, "%s/%s", com_gamedir, filename);
                if (Sys_FileTime(checkname) == -1)
                        break;  // file doesn't exist
                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 = 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);
+
+       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;
 
 
-       buffer = malloc(glwidth*glheight*3 + 18);
-       memset (buffer, 0, 18);
-       buffer[2] = 2;          // uncompressed type
-       buffer[12] = glwidth&255;
-       buffer[13] = glwidth>>8;
-       buffer[14] = glheight&255;
-       buffer[15] = glheight>>8;
-       buffer[16] = 24;        // pixel size
+       r_refdef.x = 0;
+       r_refdef.y = 0;
+       r_refdef.width = size;
+       r_refdef.height = size;
 
 
-       glReadPixels (glx, gly, glwidth, glheight, GL_RGB, GL_UNSIGNED_BYTE, buffer+18 ); 
+       r_refdef.fov_x = 90;
+       r_refdef.fov_y = 90;
 
 
-       // swap rgb to bgr
-       c = 18+glwidth*glheight*3;
-       for (i=18 ; i<c ; i+=3)
+       for (i = 0;i < 6;i++)
        {
        {
-               temp = buffer[i];
-               buffer[i] = buffer[i+2];
-               buffer[i+2] = temp;
+               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);
        }
        }
-       COM_WriteFile (pcxname, buffer, glwidth*glheight*3 + 18 );
 
 
-       free (buffer);
-       Con_Printf ("Wrote %s\n", pcxname);
-} 
+       envmap = false;
+       glDrawBuffer  (GL_BACK);
+       glReadBuffer  (GL_BACK);
 
 
+       Mem_Free(buffer);
+
+       // cause refdef to be fixed
+//     vid.recalc_refdef = 1;
+}
 
 //=============================================================================
 
 
 //=============================================================================
 
@@ -667,30 +686,28 @@ SCR_BeginLoadingPlaque
 
 ================
 */
 
 ================
 */
+/*
 void SCR_BeginLoadingPlaque (void)
 {
        S_StopAllSounds (true);
 
 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
 // 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_drawloading = true;
-       scr_fullupdate = 0;
-//     Sbar_Changed ();
        SCR_UpdateScreen ();
        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;
 }
 }
+*/
 
 /*
 ===============
 
 /*
 ===============
@@ -698,17 +715,18 @@ SCR_EndLoadingPlaque
 
 ================
 */
 
 ================
 */
+/*
 void SCR_EndLoadingPlaque (void)
 {
 void SCR_EndLoadingPlaque (void)
 {
-       scr_disabled_for_loading = false;
-       scr_fullupdate = 0;
+//     scr_disabled_for_loading = false;
+       scr_drawloading = false;
        Con_ClearNotify ();
 }
        Con_ClearNotify ();
 }
+*/
 
 //=============================================================================
 
 char   *scr_notifystring;
 
 //=============================================================================
 
 char   *scr_notifystring;
-qboolean       scr_drawdialog;
 
 void SCR_DrawNotifyString (void)
 {
 
 void SCR_DrawNotifyString (void)
 {
@@ -718,7 +736,7 @@ void SCR_DrawNotifyString (void)
 
        start = scr_notifystring;
 
 
        start = scr_notifystring;
 
-       y = vid.height*0.35;
+       y = vid.conheight*0.35;
 
        do      
        {
 
        do      
        {
@@ -726,12 +744,9 @@ 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;
-               // 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')
                y += 8;
 
                while (*start && *start != '\n')
@@ -740,113 +755,117 @@ void SCR_DrawNotifyString (void)
                if (!*start)
                        break;
                start++;                // skip the \n
                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);
+//=============================================================================
 
 
-       scr_fullupdate = 0;
-       SCR_UpdateScreen ();
+void DrawCrosshair(int num);
 
 
-       return key_lastpress == 'y';
-}
+char r_speeds_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;
 
 
-/*
-===============
-SCR_BringDownConsole
+       r_timereport_temp = r_timereport_current;
+       r_timereport_current = Sys_DoubleTime();
+       t = (int) ((r_timereport_current - r_timereport_temp) * 1000000.0);
 
 
-Brings the console down and fades the palettes back to normal
-================
-*/
-void SCR_BringDownConsole (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 palette on next frame
-       VID_SetPalette (host_basepal);
+       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;
+       }
 }
 
 }
 
-void GL_Set2D (void);
+void R_TimeReport_Start(void)
+{
+       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%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], 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_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);
 
 
-extern void SHOWLMP_drawall();
-extern cvar_t contrast;
-extern cvar_t brightness;
-extern cvar_t gl_lightmode;
+               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 GL_BrightenScreen()
+void R_TimeReport_End(void)
 {
 {
-       float f;
-       glDisable(GL_TEXTURE_2D);
-       glEnable(GL_BLEND);
-       f = brightness.value = bound(1.0f, brightness.value, 5.0f);
-       if (f > 1)
+       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)
+               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 < 1.0f)
-       {
-               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);
 }
 
 /*
 }
 
 /*
@@ -856,148 +875,93 @@ SCR_UpdateScreen
 This is called every frame, and can also be called explicitly to flush
 text to the screen.
 
 This is called every frame, and can also be called explicitly to flush
 text to the screen.
 
-WARNING: be very careful calling this from elsewhere, because the refresh
-needs almost the entire 256k of stack space!
+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();
-int c_nodes;
 void SCR_UpdateScreen (void)
 {
 void SCR_UpdateScreen (void)
 {
-       double  time1 = 0, time2;
+       VID_UpdateGamma(false);
 
 
-       if (r_speeds.value)
-       {
-               time1 = Sys_FloatTime ();
-               c_brush_polys = 0;
-               c_alias_polys = 0;
-               c_nodes = 0;
-       }
+       if (scr_disabled_for_loading)
+               return;
 
 
-       if (!gl_arrays)
-               gl_vertexarrays.value = 0;
+       if (!scr_initialized || !con_initialized)
+               return;                         // not initialized yet
 
 
-       vid.numpages = 2 + gl_triplebuffer.value;
+       //Mem_CheckSentinelsGlobal();
+       //R_TimeReport("memtest");
 
 
-       scr_copytop = 0;
-       scr_copyeverything = 0;
+       R_TimeReport("other");
 
 
-       if (scr_disabled_for_loading)
-       {
-               if (realtime - scr_disabled_time > 60)
-               {
-                       scr_disabled_for_loading = false;
-                       Con_Printf ("load failed.\n");
-               }
-               else
-                       return;
-       }
+       glFinish ();
+       CHECKGLERROR
 
 
-       if (!scr_initialized || !con_initialized)
-               return;                         // not initialized yet
+       GL_EndRendering ();
 
 
+       R_TimeReport("finish");
 
 
-       GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
-       
-       //
-       // determine size of refresh window
-       //
-       if (oldfov != scr_fov.value)
-       {
-               oldfov = scr_fov.value;
-               vid.recalc_refdef = true;
-       }
+       GL_BeginRendering (&vid.realx, &vid.realy, &vid.realwidth, &vid.realheight);
 
 
-       if (oldscreensize != scr_viewsize.value)
-       {
-               oldscreensize = scr_viewsize.value;
-               vid.recalc_refdef = true;
-       }
+       if (gl_combine.integer && !gl_combine_extension)
+               Cvar_SetValue("gl_combine", 0);
 
 
-       if (vid.recalc_refdef)
-               SCR_CalcRefdef ();
+       lighthalf = gl_lightmode.integer;
 
 
-       glClearColor(0,0,0,0);
-       glClear (GL_COLOR_BUFFER_BIT); // LordHavoc: clear the screen (around the view as well)
+       lightscalebit = 0;
+       if (lighthalf)
+               lightscalebit += 1;
 
 
-//
-// do 3D refresh drawing, and then update the screen
-//
-       SCR_SetUpToDrawConsole ();
+       if (gl_combine.integer && r_multitexture.integer)
+               lightscalebit += 2;
 
 
-       V_RenderView ();
+       lightscale = 1.0f / (float) (1 << lightscalebit);
 
 
-       GL_Set2D ();
+       R_TimeReport("setup");
 
 
-       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)
-                       Draw_Character (scr_vrect.x + scr_vrect.width/2, scr_vrect.y + scr_vrect.height/2, '+');
-               
-               SCR_DrawRam ();
-               SCR_DrawNet ();
-               SCR_DrawTurtle ();
-               SCR_DrawPause ();
-               SCR_CheckDrawCenterString ();
-               Sbar_Draw ();
-               SHOWLMP_drawall();
-               SCR_DrawConsole ();     
-               M_Draw ();
-       }
+       // determine size of refresh window
+       SCR_CalcRefdef();
+
+       R_TimeReport("calcrefdef");
 
 
-       if (showfps.value)
+       if (r_render.integer)
        {
        {
-               static double currtime;
-               double newtime;
-               char temp[32];
-               int calc;
-               newtime = Sys_FloatTime();
-               calc = (int) (100.0 / (newtime - currtime));
-               sprintf(temp, "% 4i.%02i fps", calc / 100, calc % 100);
-               currtime = newtime;
-               Draw_String(vid.width - (12*8), 0, temp, 9999);
+               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
        }
 
        }
 
-       V_UpdatePalette ();
+       SCR_SetUpToDrawConsole();
 
 
-       GL_BrightenScreen();
+       R_TimeReport("clear");
 
 
-       GL_Finish();
+       if (scr_conlines < vid.conheight)
+               R_RenderView();
 
 
-       if (r_speeds.value)
-       {
-               time2 = Sys_FloatTime ();
-               Con_Printf ("%3i ms  %4i wpoly %4i epoly %4i transpoly %4i BSPnodes\n", (int)((time2-time1)*1000), c_brush_polys, c_alias_polys, currenttranspoly, c_nodes); 
-       }
-       GL_EndRendering ();
-}
+       SCR_DrawRam();
+       SCR_DrawNet();
+       SCR_DrawTurtle();
+       SCR_DrawPause();
+       SCR_CheckDrawCenterString();
+       Sbar_Draw();
+       SHOWLMP_drawall();
 
 
-// for profiling, this is seperated
-void GL_Finish()
-{
-       glFinish ();
-}
+       SCR_DrawConsole();
+       M_Draw();
+
+       ui_draw();
+
+       R_TimeReport("2d");
 
 
+       R_TimeReport_End();
+
+       // draw 2D stuff
+       R_DrawQueue();
+
+       R_TimeReport_Start();
+}