]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_screen.c
added bufferobject and bufferoffset parameters to all R_Mesh_*Pointer functions and...
[xonotic/darkplaces.git] / cl_screen.c
index ed4d49ce55b25e1a4548d906ae8dc78b57e95d5b..581852aaa460e50d695cdc72a0e5761eafd08c67 100644 (file)
 #include "snd_main.h"
 
 cvar_t scr_viewsize = {CVAR_SAVE, "viewsize","100", "how large the view should be, 110 disables inventory bar, 120 disables status bar"};
-cvar_t scr_fov = {CVAR_SAVE, "fov","90", "field of vision, 1-170 degrees, default 90, some players use 110-130"};      // 1 - 170
+cvar_t scr_fov = {CVAR_SAVE, "fov","90", "field of vision, 1-170 degrees, default 90, some players use 110-130"};
 cvar_t scr_conalpha = {CVAR_SAVE, "scr_conalpha", "1", "opacity of console background"};
 cvar_t scr_conbrightness = {CVAR_SAVE, "scr_conbrightness", "1", "brightness of console background (0 = black, 1 = image)"};
 cvar_t scr_conforcewhiledisconnected = {0, "scr_conforcewhiledisconnected", "1", "forces fullscreen console while disconnected"};
 cvar_t scr_menuforcewhiledisconnected = {0, "scr_menuforcewhiledisconnected", "0", "forces menu while disconnected"};
 cvar_t scr_centertime = {0, "scr_centertime","2", "how long centerprint messages show"};
 cvar_t scr_showram = {CVAR_SAVE, "showram","1", "show ram icon if low on surface cache memory (not used)"};
-cvar_t scr_showturtle = {CVAR_SAVE, "showturtle","0", "show turtle icon when framerate is too low (not used)"};
+cvar_t scr_showturtle = {CVAR_SAVE, "showturtle","0", "show turtle icon when framerate is too low"};
 cvar_t scr_showpause = {CVAR_SAVE, "showpause","1", "show pause icon when game is paused"};
 cvar_t scr_showbrand = {0, "showbrand","0", "shows gfx/brand.tga in a corner of the screen (different values select different positions, including centered)"};
-cvar_t scr_printspeed = {0, "scr_printspeed","8", "speed of intermission printing (episode end texts)"};
+cvar_t scr_printspeed = {0, "scr_printspeed","0", "speed of intermission printing (episode end texts), a value of 0 disables the slow printing"};
 cvar_t vid_conwidth = {CVAR_SAVE, "vid_conwidth", "640", "virtual width of 2D graphics system"};
 cvar_t vid_conheight = {CVAR_SAVE, "vid_conheight", "480", "virtual height of 2D graphics system"};
 cvar_t vid_pixelheight = {CVAR_SAVE, "vid_pixelheight", "1", "adjusts vertical field of vision to account for non-square pixels (1280x1024 on a CRT monitor for example)"};
@@ -43,6 +43,8 @@ cvar_t scr_zoomwindow = {CVAR_SAVE, "scr_zoomwindow", "0", "displays a zoomed in
 cvar_t scr_zoomwindow_viewsizex = {CVAR_SAVE, "scr_zoomwindow_viewsizex", "20", "horizontal viewsize of zoom window"};
 cvar_t scr_zoomwindow_viewsizey = {CVAR_SAVE, "scr_zoomwindow_viewsizey", "20", "vertical viewsize of zoom window"};
 cvar_t scr_zoomwindow_fov = {CVAR_SAVE, "scr_zoomwindow_fov", "20", "fov of zoom window"};
+cvar_t scr_stipple = {0, "scr_stipple", "0", "interlacing-like stippling of the display"};
+cvar_t scr_refresh = {0, "scr_refresh", "1", "allows you to completely shut off rendering for benchmarking purposes"};
 
 
 int jpeg_supported = false;
@@ -107,8 +109,8 @@ void SCR_DrawCenterString (void)
        int             remaining;
        int             color;
 
-// the finale prints the characters one at a time
-       if (cl.intermission)
+// the finale prints the characters one at a time, except if printspeed is an absurdly high value
+       if (cl.intermission && scr_printspeed.value > 0 && scr_printspeed.value < 1000000)
                remaining = (int)(scr_printspeed.value * (cl.time - scr_centertime_start));
        else
                remaining = 9999;
@@ -166,7 +168,8 @@ void SCR_CheckDrawCenterString (void)
        if (scr_center_lines > scr_erase_lines)
                scr_erase_lines = scr_center_lines;
 
-       scr_centertime_off -= cl.realframetime;
+       if (cl.time > cl.oldtime)
+               scr_centertime_off -= cl.time - cl.oldtime;
 
        // don't draw if this is a normal stats-screen intermission,
        // only if it is not an intermission, or a finale intermission
@@ -315,8 +318,22 @@ static int SCR_DrawQWDownload(int offset)
        float size = 8;
        char temp[256];
        if (!cls.qw_downloadname[0])
+       {
+               cls.qw_downloadspeedrate = 0;
+               cls.qw_downloadspeedtime = realtime;
+               cls.qw_downloadspeedcount = 0;
                return 0;
-       dpsnprintf(temp, sizeof(temp), "Downloading %s ...  %3i%%\n", cls.qw_downloadname, cls.qw_downloadpercent);
+       }
+       if (realtime >= cls.qw_downloadspeedtime + 1)
+       {
+               cls.qw_downloadspeedrate = cls.qw_downloadspeedcount;
+               cls.qw_downloadspeedtime = realtime;
+               cls.qw_downloadspeedcount = 0;
+       }
+       if (cls.protocol == PROTOCOL_QUAKEWORLD)
+               dpsnprintf(temp, sizeof(temp), "Downloading %s %3i%% (%i) at %i bytes/s\n", cls.qw_downloadname, cls.qw_downloadpercent, cls.qw_downloadmemorycursize, cls.qw_downloadspeedrate);
+       else
+               dpsnprintf(temp, sizeof(temp), "Downloading %s %3i%% (%i/%i) at %i bytes/s\n", cls.qw_downloadname, cls.qw_downloadpercent, cls.qw_downloadmemorycursize, cls.qw_downloadmemorymaxsize, cls.qw_downloadspeedrate);
        len = (int)strlen(temp);
        x = (vid_conwidth.integer - len*size) / 2;
        y = vid_conheight.integer - size - offset;
@@ -460,7 +477,7 @@ void SCR_BeginLoadingPlaque (void)
 
        Host_StartVideo();
        S_StopAllSounds();
-       SCR_UpdateLoadingScreen();
+       SCR_UpdateLoadingScreen(false);
 }
 
 //=============================================================================
@@ -498,6 +515,7 @@ void R_TimeReport(char *desc)
 void R_TimeReport_Frame(void)
 {
        int i, j, lines, y;
+       cl_locnode_t *loc;
 
        if (r_speeds_string[0])
        {
@@ -535,6 +553,11 @@ void R_TimeReport_Frame(void)
                speedstringcount = 0;
                r_speeds_string[0] = 0;
                r_timereport_active = false;
+               // put the location name in the r_speeds display as it greatly helps
+               // when creating loc files
+               loc = CL_Locs_FindNearest(cl.movement_origin);
+               if (loc)
+                       sprintf(r_speeds_string + strlen(r_speeds_string), "Location: %s\n", loc->name);
                sprintf(r_speeds_string + strlen(r_speeds_string), "org:'%+8.2f %+8.2f %+8.2f' dir:'%+2.3f %+2.3f %+2.3f'\n", r_view.origin[0], r_view.origin[1], r_view.origin[2], r_view.forward[0], r_view.forward[1], r_view.forward[2]);
                sprintf(r_speeds_string + strlen(r_speeds_string), "%5i entities%6i surfaces%6i triangles%5i leafs%5i portals%6i particles\n", r_refdef.stats.entities, r_refdef.stats.entities_surfaces, r_refdef.stats.entities_triangles, r_refdef.stats.world_leafs, r_refdef.stats.world_portals, r_refdef.stats.particles);
                sprintf(r_speeds_string + strlen(r_speeds_string), "%4i lights%4i clears%4i scissored%7i light%7i shadow%7i dynamic\n", r_refdef.stats.lights, r_refdef.stats.lights_clears, r_refdef.stats.lights_scissored, r_refdef.stats.lights_lighttriangles, r_refdef.stats.lights_shadowtriangles, r_refdef.stats.lights_dynamicshadowtriangles);
@@ -612,6 +635,8 @@ void CL_Screen_Init(void)
        Cvar_RegisterVariable(&scr_zoomwindow_viewsizex);
        Cvar_RegisterVariable(&scr_zoomwindow_viewsizey);
        Cvar_RegisterVariable(&scr_zoomwindow_fov);
+       Cvar_RegisterVariable(&scr_stipple);
+       Cvar_RegisterVariable(&scr_refresh);
 
        Cmd_AddCommand ("sizeup",SCR_SizeUp_f, "increase view size (increases viewsize cvar)");
        Cmd_AddCommand ("sizedown",SCR_SizeDown_f, "decrease view size (decreases viewsize cvar)");
@@ -810,11 +835,9 @@ static void SCR_CaptureVideo_RIFF_OverflowCheck(int framesize)
        cursize = SCR_CaptureVideo_RIFF_GetPosition() - cls.capturevideo.riffstackstartoffset[0];
        // if this would overflow the windows limit of 1GB per RIFF chunk, we need
        // to close the current RIFF chunk and open another for future frames
-       if (8 + cursize + framesize > 1<<30)
+       if (8 + cursize + framesize + cls.capturevideo.riffindexbuffer.cursize + 8 > 1<<30)
        {
                SCR_CaptureVideo_RIFF_Finish();
-               while (cls.capturevideo.riffstacklevel > 0)
-                       SCR_CaptureVideo_RIFF_Pop();
                // begin a new 1GB extended section of the AVI
                SCR_CaptureVideo_RIFF_Push("RIFF", "AVIX");
                SCR_CaptureVideo_RIFF_Push("LIST", "movi");
@@ -826,7 +849,6 @@ void SCR_CaptureVideo_BeginVideo(void)
        double gamma, g;
        int width = vid.width, height = vid.height, x;
        unsigned int i;
-       unsigned char out[44];
        if (cls.capturevideo.active)
                return;
        memset(&cls.capturevideo, 0, sizeof(cls.capturevideo));
@@ -995,6 +1017,8 @@ Cr = R *  .500 + G * -.419 + B * -.0813 + 128.;
                SCR_CaptureVideo_RIFF_Push("ISFT", NULL);
                SCR_CaptureVideo_RIFF_WriteTerminatedString(engineversion);
                SCR_CaptureVideo_RIFF_Pop();
+               // enable this junk filler if you like the LIST movi to always begin at 4KB in the file (why?)
+#if 0
                SCR_CaptureVideo_RIFF_Push("JUNK", NULL);
                x = 4096 - SCR_CaptureVideo_RIFF_GetPosition();
                while (x > 0)
@@ -1005,6 +1029,7 @@ Cr = R *  .500 + G * -.419 + B * -.0813 + 128.;
                        x -= i;
                }
                SCR_CaptureVideo_RIFF_Pop();
+#endif
                SCR_CaptureVideo_RIFF_Pop();
                // begin the actual video section now
                SCR_CaptureVideo_RIFF_Push("LIST", "movi");
@@ -1025,8 +1050,6 @@ Cr = R *  .500 + G * -.419 + B * -.0813 + 128.;
 
 void SCR_CaptureVideo_EndVideo(void)
 {
-       int i, n;
-       unsigned char out[44];
        if (!cls.capturevideo.active)
                return;
        cls.capturevideo.active = false;
@@ -1120,7 +1143,6 @@ qboolean SCR_CaptureVideo_VideoFrame(int newframenum)
 {
        int x = 0, y = 0, width = vid.width, height = vid.height;
        unsigned char *in, *out;
-       char filename[32];
        CHECKGLERROR
        //return SCR_ScreenShot(filename, cls.capturevideo.buffer, cls.capturevideo.buffer + vid.width * vid.height * 3, cls.capturevideo.buffer + vid.width * vid.height * 6, 0, 0, vid.width, vid.height, false, false, false, jpeg, true);
        // speed is critical here, so do saving as directly as possible
@@ -1522,8 +1544,6 @@ void SCR_DrawScreen (void)
 
                if(!CL_VM_UpdateView())
                        R_RenderView();
-               else
-                       SCR_DrawConsole();
 
                if (scr_zoomwindow.integer)
                {
@@ -1559,9 +1579,6 @@ void SCR_DrawScreen (void)
 
        // draw 2D stuff
 
-       //FIXME: force menu if nothing else to look at?
-       //if (key_dest == key_game && cls.signon != SIGNONS && cls.state == ca_disconnected)
-
        if (cls.signon == SIGNONS)
        {
                SCR_DrawNet ();
@@ -1576,8 +1593,7 @@ void SCR_DrawScreen (void)
        CL_DrawVideo();
        R_Shadow_EditLights_DrawSelectedLightProperties();
 
-       if(!csqc_loaded)
-               SCR_DrawConsole();
+       SCR_DrawConsole();
 
        SCR_DrawBrand();
 
@@ -1599,23 +1615,26 @@ void SCR_DrawScreen (void)
                R_TimeReport("meshfinish");
 }
 
-void SCR_UpdateLoadingScreen (void)
+void SCR_UpdateLoadingScreen (qboolean clear)
 {
        float x, y;
        cachepic_t *pic;
        float vertex3f[12];
        float texcoord2f[8];
        // don't do anything if not initialized yet
-       if (vid_hidden)
+       if (vid_hidden || !scr_refresh.integer)
                return;
        CHECKGLERROR
        qglViewport(0, 0, vid.width, vid.height);CHECKGLERROR
        //qglDisable(GL_SCISSOR_TEST);CHECKGLERROR
        //qglDepthMask(1);CHECKGLERROR
        qglColorMask(1,1,1,1);CHECKGLERROR
-       //qglClearColor(0,0,0,0);CHECKGLERROR
-       //qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
-       //qglCullFace(GL_FRONT);CHECKGLERROR
+       qglClearColor(0,0,0,0);CHECKGLERROR
+       // when starting up a new video mode, make sure the screen is cleared to black
+       if (clear)
+       {
+               qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
+       }
        //qglDisable(GL_CULL_FACE);CHECKGLERROR
        //R_ClearScreen();
        R_Textures_Frame();
@@ -1629,11 +1648,11 @@ void SCR_UpdateLoadingScreen (void)
        GL_Color(1,1,1,1);
        GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        GL_DepthTest(false);
-       R_Mesh_VertexPointer(vertex3f);
-       R_Mesh_ColorPointer(NULL);
+       R_Mesh_VertexPointer(vertex3f, 0, 0);
+       R_Mesh_ColorPointer(NULL, 0, 0);
        R_Mesh_ResetTextureState();
        R_Mesh_TexBind(0, R_GetTexture(pic->tex));
-       R_Mesh_TexCoordPointer(0, 2, texcoord2f);
+       R_Mesh_TexCoordPointer(0, 2, texcoord2f, 0, 0);
        vertex3f[2] = vertex3f[5] = vertex3f[8] = vertex3f[11] = 0;
        vertex3f[0] = vertex3f[9] = x;
        vertex3f[1] = vertex3f[4] = y;
@@ -1643,31 +1662,36 @@ void SCR_UpdateLoadingScreen (void)
        texcoord2f[2] = 1;texcoord2f[3] = 0;
        texcoord2f[4] = 1;texcoord2f[5] = 1;
        texcoord2f[6] = 0;texcoord2f[7] = 1;
-       R_Mesh_Draw(0, 4, 2, polygonelements);
+       if (vid.stereobuffer)
+       {
+               qglDrawBuffer(GL_FRONT_LEFT);
+               R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
+               qglDrawBuffer(GL_FRONT_RIGHT);
+               R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
+       }
+       else
+       {
+               qglDrawBuffer(GL_FRONT);
+               R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
+       }
        R_Mesh_Finish();
        // refresh
-       VID_Finish(false);
+       // not necessary when rendering to GL_FRONT buffers
+       //VID_Finish(false);
+       // however this IS necessary on Windows Vista
+       qglFinish();
 }
 
 void CL_UpdateScreen(void)
 {
        float conwidth, conheight;
 
-       if (vid_hidden)
+       if (vid_hidden || !scr_refresh.integer)
                return;
 
-       if (!scr_initialized || !con_initialized || vid_hidden)
+       if (!scr_initialized || !con_initialized)
                return;                         // not initialized yet
 
-       // don't allow cheats in multiplayer
-       if (!cl.islocalgame && cl.worldmodel)
-       {
-               if (r_fullbright.integer != 0)
-                       Cvar_Set ("r_fullbright", "0");
-               if (r_ambient.value != 0)
-                       Cvar_Set ("r_ambient", "0");
-       }
-
        conwidth = bound(320, vid_conwidth.value, 2048);
        conheight = bound(200, vid_conheight.value, 1536);
        if (vid_conwidth.value != conwidth)
@@ -1730,15 +1754,37 @@ void CL_UpdateScreen(void)
        qglClearColor(0,0,0,0);CHECKGLERROR
        qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
 
+       if(scr_stipple.integer)
+       {
+               GLubyte stipple[128];
+               int i, s, width, parts;
+               static int frame = 0;
+               ++frame;
+
+               s = scr_stipple.integer;
+               parts = (s & 007);
+               width = (s & 070) >> 3;
+
+               qglEnable(GL_POLYGON_STIPPLE); // 0x0B42
+               for(i = 0; i < 128; ++i)
+               {
+                       int line = i/4;
+                       stipple[i] = (((line >> width) + frame) & ((1 << parts) - 1)) ? 0x00 : 0xFF;
+               }
+               qglPolygonStipple(stipple);
+       }
+       else
+               qglDisable(GL_POLYGON_STIPPLE);
+
        if (r_timereport_active)
                R_TimeReport("clear");
 
-       if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer || r_stereo_sidebyside.integer)
+       if (vid.stereobuffer || r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer || r_stereo_sidebyside.integer)
        {
                matrix4x4_t originalmatrix = r_view.matrix;
-               r_view.matrix.m[0][3] = originalmatrix.m[0][3] + r_stereo_separation.value * -0.5f * r_view.matrix.m[0][1];
-               r_view.matrix.m[1][3] = originalmatrix.m[1][3] + r_stereo_separation.value * -0.5f * r_view.matrix.m[1][1];
-               r_view.matrix.m[2][3] = originalmatrix.m[2][3] + r_stereo_separation.value * -0.5f * r_view.matrix.m[2][1];
+               matrix4x4_t offsetmatrix;
+               Matrix4x4_CreateTranslate(&offsetmatrix, 0, r_stereo_separation.value * -0.5f, 0);
+               Matrix4x4_Concat(&r_view.matrix, &originalmatrix, &offsetmatrix);
 
                if (r_stereo_sidebyside.integer)
                        r_stereo_side = 0;
@@ -1750,11 +1796,13 @@ void CL_UpdateScreen(void)
                        r_view.colormask[2] = 0;
                }
 
+               if (vid.stereobuffer)
+                       qglDrawBuffer(GL_BACK_RIGHT);
+
                SCR_DrawScreen();
 
-               r_view.matrix.m[0][3] = originalmatrix.m[0][3] + r_stereo_separation.value * 0.5f * r_view.matrix.m[0][1];
-               r_view.matrix.m[1][3] = originalmatrix.m[1][3] + r_stereo_separation.value * 0.5f * r_view.matrix.m[1][1];
-               r_view.matrix.m[2][3] = originalmatrix.m[2][3] + r_stereo_separation.value * 0.5f * r_view.matrix.m[2][1];
+               Matrix4x4_CreateTranslate(&offsetmatrix, 0, r_stereo_separation.value * 0.5f, 0);
+               Matrix4x4_Concat(&r_view.matrix, &originalmatrix, &offsetmatrix);
 
                if (r_stereo_sidebyside.integer)
                        r_stereo_side = 1;
@@ -1766,12 +1814,18 @@ void CL_UpdateScreen(void)
                        r_view.colormask[2] = r_stereo_redcyan.integer || r_stereo_redblue.integer;
                }
 
+               if (vid.stereobuffer)
+                       qglDrawBuffer(GL_BACK_LEFT);
+
                SCR_DrawScreen();
 
                r_view.matrix = originalmatrix;
        }
        else
+       {
+               qglDrawBuffer(GL_BACK);
                SCR_DrawScreen();
+       }
 
        SCR_CaptureVideo();