]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_screen.c
Rework game specific hacks to have a special group for Nexuiz-derived games.
[xonotic/darkplaces.git] / cl_screen.c
index 0f22782701646e3098bff4ddf386a4f4ac87c2c6..4b6100f835a6ddc4c4253dad5c9a67ee298cabf4 100644 (file)
@@ -7,8 +7,10 @@
 #include "cl_collision.h"
 #include "libcurl.h"
 #include "csprogs.h"
+#ifdef CONFIG_VIDEO_CAPTURE
 #include "cap_avi.h"
 #include "cap_ogg.h"
+#endif
 
 // we have to include snd_main.h here only to get access to snd_renderbuffer->format.speed when writing the AVI headers
 #include "snd_main.h"
@@ -27,7 +29,9 @@ cvar_t scr_conscroll2_x = {CVAR_SAVE, "scr_conscroll2_x", "0", "scroll speed of
 cvar_t scr_conscroll2_y = {CVAR_SAVE, "scr_conscroll2_y", "0", "scroll speed of gfx/conback2 in y direction"};
 cvar_t scr_conscroll3_x = {CVAR_SAVE, "scr_conscroll3_x", "0", "scroll speed of gfx/conback3 in x direction"};
 cvar_t scr_conscroll3_y = {CVAR_SAVE, "scr_conscroll3_y", "0", "scroll speed of gfx/conback3 in y direction"};
+#ifdef CONFIG_MENU
 cvar_t scr_menuforcewhiledisconnected = {0, "scr_menuforcewhiledisconnected", "0", "forces menu while disconnected"};
+#endif
 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"};
@@ -53,9 +57,10 @@ cvar_t scr_screenshot_jpeg_quality = {CVAR_SAVE, "scr_screenshot_jpeg_quality","
 cvar_t scr_screenshot_png = {CVAR_SAVE, "scr_screenshot_png","0", "save png instead of targa"};
 cvar_t scr_screenshot_gammaboost = {CVAR_SAVE, "scr_screenshot_gammaboost","1", "gamma correction on saved screenshots and videos, 1.0 saves unmodified images"};
 cvar_t scr_screenshot_hwgamma = {CVAR_SAVE, "scr_screenshot_hwgamma","1", "apply the video gamma ramp to saved screenshots and videos"};
-cvar_t scr_screenshot_alpha = {CVAR_SAVE, "scr_screenshot_alpha","0", "try to write an alpha channel to screenshots (debugging feature)"};
+cvar_t scr_screenshot_alpha = {0, "scr_screenshot_alpha","0", "try to write an alpha channel to screenshots (debugging feature)"};
 cvar_t scr_screenshot_timestamp = {CVAR_SAVE, "scr_screenshot_timestamp", "1", "use a timestamp based number of the type YYYYMMDDHHMMSSsss instead of sequential numbering"};
 // scr_screenshot_name is defined in fs.c
+#ifdef CONFIG_VIDEO_CAPTURE
 cvar_t cl_capturevideo = {0, "cl_capturevideo", "0", "enables saving of video to a .avi file using uncompressed I420 colorspace and PCM audio, note that scr_screenshot_gammaboost affects the brightness of the output)"};
 cvar_t cl_capturevideo_demo_stop = {CVAR_SAVE, "cl_capturevideo_demo_stop", "1", "automatically stops video recording when demo ends"};
 cvar_t cl_capturevideo_printfps = {CVAR_SAVE, "cl_capturevideo_printfps", "1", "prints the frames per second captured in capturevideo (is only written to the log file, not to the console, as that would be visible on the video)"};
@@ -67,6 +72,7 @@ cvar_t cl_capturevideo_nameformat = {CVAR_SAVE, "cl_capturevideo_nameformat", "d
 cvar_t cl_capturevideo_number = {CVAR_SAVE, "cl_capturevideo_number", "1", "number to append to video filename, incremented each time a capture begins"};
 cvar_t cl_capturevideo_ogg = {CVAR_SAVE, "cl_capturevideo_ogg", "1", "save captured video data as Ogg/Vorbis/Theora streams"};
 cvar_t cl_capturevideo_framestep = {CVAR_SAVE, "cl_capturevideo_framestep", "1", "when set to n >= 1, render n frames to capture one (useful for motion blur like effects)"};
+#endif
 cvar_t r_letterbox = {0, "r_letterbox", "0", "reduces vertical height of view to simulate a letterboxed movie effect (can be used by mods for cutscenes)"};
 cvar_t r_stereo_separation = {0, "r_stereo_separation", "4", "separation distance of eyes in the world (negative values are only useful for cross-eyed viewing)"};
 cvar_t r_stereo_sidebyside = {0, "r_stereo_sidebyside", "0", "side by side views for those who can't afford glasses but can afford eye strain (note: use a negative r_stereo_separation if you want cross-eyed viewing)"};
@@ -82,7 +88,7 @@ cvar_t scr_screenshot_name_in_mapdir = {CVAR_SAVE, "scr_screenshot_name_in_mapdi
 cvar_t shownetgraph = {CVAR_SAVE, "shownetgraph", "0", "shows a graph of packet sizes and other information, 0 = off, 1 = show client netgraph, 2 = show client and server netgraphs (when hosting a server)"};
 cvar_t cl_demo_mousegrab = {0, "cl_demo_mousegrab", "0", "Allows reading the mouse input while playing demos. Useful for camera mods developed in csqc. (0: never, 1: always)"};
 cvar_t timedemo_screenshotframelist = {0, "timedemo_screenshotframelist", "", "when performing a timedemo, take screenshots of each frame in this space-separated list - example: 1 201 401"};
-cvar_t vid_touchscreen_outlinealpha = {0, "vid_touchscreen_outlinealpha", "0.25", "opacity of touchscreen area outlines"};
+cvar_t vid_touchscreen_outlinealpha = {0, "vid_touchscreen_outlinealpha", "0", "opacity of touchscreen area outlines"};
 cvar_t vid_touchscreen_overlayalpha = {0, "vid_touchscreen_overlayalpha", "0.25", "opacity of touchscreen area icons"};
 cvar_t r_speeds_graph = {CVAR_SAVE, "r_speeds_graph", "0", "display a graph of renderer statistics "};
 cvar_t r_speeds_graph_filter[8] =
@@ -244,16 +250,16 @@ static void SCR_CheckDrawCenterString (void)
        SCR_DrawCenterString ();
 }
 
-static void SCR_DrawNetGraph_DrawGraph (int graphx, int graphy, int graphwidth, int graphheight, float graphscale, const char *label, float textsize, int packetcounter, netgraphitem_t *netgraph)
+static void SCR_DrawNetGraph_DrawGraph (int graphx, int graphy, int graphwidth, int graphheight, float graphscale, int graphlimit, const char *label, float textsize, int packetcounter, netgraphitem_t *netgraph)
 {
        netgraphitem_t *graph;
        int j, x, y, numlines;
        int totalbytes = 0;
        char bytesstring[128];
-       float g[NETGRAPH_PACKETS][6];
+       float g[NETGRAPH_PACKETS][7];
        float *a;
        float *b;
-       r_vertexgeneric_t vertex[(NETGRAPH_PACKETS+2)*5*2];
+       r_vertexgeneric_t vertex[(NETGRAPH_PACKETS+2)*6*2];
        r_vertexgeneric_t *v;
        DrawQ_Fill(graphx, graphy, graphwidth, graphheight + textsize * 2, 0, 0, 0, 0.5, 0);
        // draw the bar graph itself
@@ -267,12 +273,16 @@ static void SCR_DrawNetGraph_DrawGraph (int graphx, int graphy, int graphwidth,
                g[j][3] = 1.0f;
                g[j][4] = 1.0f;
                g[j][5] = 1.0f;
+               g[j][6] = 1.0f;
                if (graph->unreliablebytes == NETGRAPH_LOSTPACKET)
                        g[j][1] = 0.00f;
                else if (graph->unreliablebytes == NETGRAPH_CHOKEDPACKET)
-                       g[j][2] = 0.96f;
+                       g[j][2] = 0.90f;
                else
                {
+                       if(netgraph[j].time >= netgraph[(j+NETGRAPH_PACKETS-1)%NETGRAPH_PACKETS].time)
+                               if(graph->unreliablebytes + graph->reliablebytes + graph->ackbytes >= graphlimit * (netgraph[j].time - netgraph[(j+NETGRAPH_PACKETS-1)%NETGRAPH_PACKETS].time))
+                                       g[j][2] = 0.98f;
                        g[j][3] = 1.0f    - graph->unreliablebytes * graphscale;
                        g[j][4] = g[j][3] - graph->reliablebytes   * graphscale;
                        g[j][5] = g[j][4] - graph->ackbytes        * graphscale;
@@ -280,11 +290,14 @@ static void SCR_DrawNetGraph_DrawGraph (int graphx, int graphy, int graphwidth,
                        if (realtime - graph->time < 1.0f)
                                totalbytes += graph->unreliablebytes + graph->reliablebytes + graph->ackbytes;
                }
+               if(graph->cleartime >= 0)
+                       g[j][6] = 0.5f + 0.5f * (2.0 / M_PI) * atan((M_PI / 2.0) * (graph->cleartime - graph->time));
                g[j][1] = bound(0.0f, g[j][1], 1.0f);
                g[j][2] = bound(0.0f, g[j][2], 1.0f);
                g[j][3] = bound(0.0f, g[j][3], 1.0f);
                g[j][4] = bound(0.0f, g[j][4], 1.0f);
                g[j][5] = bound(0.0f, g[j][5], 1.0f);
+               g[j][6] = bound(0.0f, g[j][6], 1.0f);
        }
        // render the lines for the graph
        numlines = 0;
@@ -310,11 +323,14 @@ static void SCR_DrawNetGraph_DrawGraph (int graphx, int graphy, int graphwidth,
                VectorSet(v->vertex3f, graphx + graphwidth * a[0], graphy + graphheight * a[3], 0.0f);Vector4Set(v->color4f, 1.0f, 0.5f, 0.0f, 1.0f);Vector2Set(v->texcoord2f, 0.0f, 0.0f);v++;
                VectorSet(v->vertex3f, graphx + graphwidth * b[0], graphy + graphheight * b[3], 0.0f);Vector4Set(v->color4f, 1.0f, 0.5f, 0.0f, 1.0f);Vector2Set(v->texcoord2f, 0.0f, 0.0f);v++;
 
-               numlines += 5;
+               VectorSet(v->vertex3f, graphx + graphwidth * a[0], graphy + graphheight * a[6], 0.0f);Vector4Set(v->color4f, 0.0f, 0.0f, 1.0f, 1.0f);Vector2Set(v->texcoord2f, 0.0f, 0.0f);v++;
+               VectorSet(v->vertex3f, graphx + graphwidth * b[0], graphy + graphheight * b[6], 0.0f);Vector4Set(v->color4f, 0.0f, 0.0f, 1.0f, 1.0f);Vector2Set(v->texcoord2f, 0.0f, 0.0f);v++;
+
+               numlines += 6;
        }
        if (numlines > 0)
        {
-               R_Mesh_PrepareVertices_Generic(numlines*2, vertex, NULL);
+               R_Mesh_PrepareVertices_Generic(numlines*2, vertex, NULL, 0);
                DrawQ_Lines(0.0f, numlines, 0, false);
        }
        x = graphx;
@@ -331,7 +347,7 @@ SCR_DrawNetGraph
 */
 static void SCR_DrawNetGraph (void)
 {
-       int i, separator1, separator2, graphwidth, graphheight, netgraph_x, netgraph_y, textsize, index, netgraphsperrow;
+       int i, separator1, separator2, graphwidth, graphheight, netgraph_x, netgraph_y, textsize, index, netgraphsperrow, graphlimit;
        float graphscale;
        netconn_t *c;
        char vabuf[1024];
@@ -349,6 +365,7 @@ static void SCR_DrawNetGraph (void)
        graphwidth = 120;
        graphheight = 70;
        graphscale = 1.0f / 1500.0f;
+       graphlimit = cl_rate.integer;
 
        netgraphsperrow = (vid_conwidth.integer + separator2) / (graphwidth * 2 + separator1 + separator2);
        netgraphsperrow = max(netgraphsperrow, 1);
@@ -357,8 +374,8 @@ static void SCR_DrawNetGraph (void)
        netgraph_x = (vid_conwidth.integer + separator2) - (1 + (index % netgraphsperrow)) * (graphwidth * 2 + separator1 + separator2);
        netgraph_y = (vid_conheight.integer - 48 - sbar_info_pos.integer + separator2) - (1 + (index / netgraphsperrow)) * (graphheight + textsize + separator2);
        c = cls.netcon;
-       SCR_DrawNetGraph_DrawGraph(netgraph_x                          , netgraph_y, graphwidth, graphheight, graphscale, "incoming", textsize, c->incoming_packetcounter, c->incoming_netgraph);
-       SCR_DrawNetGraph_DrawGraph(netgraph_x + graphwidth + separator1, netgraph_y, graphwidth, graphheight, graphscale, "outgoing", textsize, c->outgoing_packetcounter, c->outgoing_netgraph);
+       SCR_DrawNetGraph_DrawGraph(netgraph_x                          , netgraph_y, graphwidth, graphheight, graphscale, graphlimit, "incoming", textsize, c->incoming_packetcounter, c->incoming_netgraph);
+       SCR_DrawNetGraph_DrawGraph(netgraph_x + graphwidth + separator1, netgraph_y, graphwidth, graphheight, graphscale, graphlimit, "outgoing", textsize, c->outgoing_packetcounter, c->outgoing_netgraph);
        index++;
 
        if (sv.active && shownetgraph.integer >= 2)
@@ -370,8 +387,8 @@ static void SCR_DrawNetGraph (void)
                                continue;
                        netgraph_x = (vid_conwidth.integer + separator2) - (1 + (index % netgraphsperrow)) * (graphwidth * 2 + separator1 + separator2);
                        netgraph_y = (vid_conheight.integer - 48 + separator2) - (1 + (index / netgraphsperrow)) * (graphheight + textsize + separator2);
-                       SCR_DrawNetGraph_DrawGraph(netgraph_x                          , netgraph_y, graphwidth, graphheight, graphscale, va(vabuf, sizeof(vabuf), "%s", svs.clients[i].name), textsize, c->outgoing_packetcounter, c->outgoing_netgraph);
-                       SCR_DrawNetGraph_DrawGraph(netgraph_x + graphwidth + separator1, netgraph_y, graphwidth, graphheight, graphscale, ""                           , textsize, c->incoming_packetcounter, c->incoming_netgraph);
+                       SCR_DrawNetGraph_DrawGraph(netgraph_x                          , netgraph_y, graphwidth, graphheight, graphscale, graphlimit, va(vabuf, sizeof(vabuf), "%s", svs.clients[i].name), textsize, c->outgoing_packetcounter, c->outgoing_netgraph);
+                       SCR_DrawNetGraph_DrawGraph(netgraph_x + graphwidth + separator1, netgraph_y, graphwidth, graphheight, graphscale, graphlimit, ""                           , textsize, c->incoming_packetcounter, c->incoming_netgraph);
                        index++;
                }
        }
@@ -681,6 +698,7 @@ static void SCR_SetUpToDrawConsole (void)
 
        Con_CheckResize ();
 
+#ifdef CONFIG_MENU
        if (scr_menuforcewhiledisconnected.integer && key_dest == key_game && cls.state == ca_disconnected)
        {
                if (framecounter >= 2)
@@ -689,6 +707,7 @@ static void SCR_SetUpToDrawConsole (void)
                        framecounter++;
        }
        else
+#endif
                framecounter = 0;
 
        if (scr_conforcewhiledisconnected.integer && key_dest == key_game && cls.signon != SIGNONS)
@@ -785,6 +804,14 @@ const char *r_stat_name[r_stat_count] =
        "vertexbufferuploadsize",
        "framedatacurrent",
        "framedatasize",
+       "bufferdatacurrent_vertex", // R_BUFFERDATA_ types are added to this index
+       "bufferdatacurrent_index16",
+       "bufferdatacurrent_index32",
+       "bufferdatacurrent_uniform",
+       "bufferdatasize_vertex", // R_BUFFERDATA_ types are added to this index
+       "bufferdatasize_index16",
+       "bufferdatasize_index32",
+       "bufferdatasize_uniform",
        "animcache_vertexmesh_count",
        "animcache_vertexmesh_vertices",
        "animcache_vertexmesh_maxvertices",
@@ -878,6 +905,26 @@ const char *r_stat_name[r_stat_count] =
        "dynamic_surfaces_because_derived",
        "dynamic_vertices_because_derived",
        "dynamic_triangles_because_derived",
+       "entitycache_count",
+       "entitycache_surfaces",
+       "entitycache_vertices",
+       "entitycache_triangles",
+       "entityanimate_count",
+       "entityanimate_surfaces",
+       "entityanimate_vertices",
+       "entityanimate_triangles",
+       "entityskeletal_count",
+       "entityskeletal_surfaces",
+       "entityskeletal_vertices",
+       "entityskeletal_triangles",
+       "entitystatic_count",
+       "entitystatic_surfaces",
+       "entitystatic_vertices",
+       "entitystatic_triangles",
+       "entitycustom_count",
+       "entitycustom_surfaces",
+       "entitycustom_vertices",
+       "entitycustom_triangles",
 };
 
 char r_speeds_timestring[4096];
@@ -1054,7 +1101,7 @@ static void R_TimeReport_EndFrame(void)
                        cls.r_speeds_graph_current = 0;
                        if (cls.r_speeds_graph_data)
                                Mem_Free(cls.r_speeds_graph_data);
-                       cls.r_speeds_graph_data = Mem_Alloc(cls.permanentmempool, cls.r_speeds_graph_length * sizeof(r_refdef.stats));
+                       cls.r_speeds_graph_data = (int *)Mem_Alloc(cls.permanentmempool, cls.r_speeds_graph_length * sizeof(r_refdef.stats));
                        // initialize the graph to have the current values throughout history
                        graph_data = cls.r_speeds_graph_data;
                        graph_length = cls.r_speeds_graph_length;
@@ -1257,10 +1304,14 @@ static void SCR_SizeDown_f (void)
        Cvar_SetValue ("viewsize",scr_viewsize.value-10);
 }
 
+#ifdef CONFIG_VIDEO_CAPTURE
 void SCR_CaptureVideo_EndVideo(void);
+#endif
 void CL_Screen_Shutdown(void)
 {
+#ifdef CONFIG_VIDEO_CAPTURE
        SCR_CaptureVideo_EndVideo();
+#endif
 }
 
 void CL_Screen_Init(void)
@@ -1280,7 +1331,9 @@ void CL_Screen_Init(void)
        Cvar_RegisterVariable (&scr_conscroll3_y);
        Cvar_RegisterVariable (&scr_conbrightness);
        Cvar_RegisterVariable (&scr_conforcewhiledisconnected);
+#ifdef CONFIG_MENU
        Cvar_RegisterVariable (&scr_menuforcewhiledisconnected);
+#endif
        Cvar_RegisterVariable (&scr_loadingscreen_background);
        Cvar_RegisterVariable (&scr_loadingscreen_scale);
        Cvar_RegisterVariable (&scr_loadingscreen_scale_base);
@@ -1309,6 +1362,7 @@ void CL_Screen_Init(void)
        Cvar_RegisterVariable (&scr_screenshot_name_in_mapdir);
        Cvar_RegisterVariable (&scr_screenshot_alpha);
        Cvar_RegisterVariable (&scr_screenshot_timestamp);
+#ifdef CONFIG_VIDEO_CAPTURE
        Cvar_RegisterVariable (&cl_capturevideo);
        Cvar_RegisterVariable (&cl_capturevideo_demo_stop);
        Cvar_RegisterVariable (&cl_capturevideo_printfps);
@@ -1320,6 +1374,7 @@ void CL_Screen_Init(void)
        Cvar_RegisterVariable (&cl_capturevideo_number);
        Cvar_RegisterVariable (&cl_capturevideo_ogg);
        Cvar_RegisterVariable (&cl_capturevideo_framestep);
+#endif
        Cvar_RegisterVariable (&r_letterbox);
        Cvar_RegisterVariable(&r_stereo_separation);
        Cvar_RegisterVariable(&r_stereo_sidebyside);
@@ -1356,7 +1411,9 @@ void CL_Screen_Init(void)
        Cmd_AddCommand ("envmap", R_Envmap_f, "render a cubemap (skybox) of the current scene");
        Cmd_AddCommand ("infobar", SCR_InfoBar_f, "display a text in the infobar (usage: infobar expiretime string)");
 
+#ifdef CONFIG_VIDEO_CAPTURE
        SCR_CaptureVideo_Ogg_Init();
+#endif
 
        scr_initialized = true;
 }
@@ -1484,6 +1541,7 @@ void SCR_ScreenShot_f (void)
        Mem_Free (buffer2);
 }
 
+#ifdef CONFIG_VIDEO_CAPTURE
 static void SCR_CaptureVideo_BeginVideo(void)
 {
        double r, g, b;
@@ -1760,6 +1818,7 @@ static void SCR_CaptureVideo(void)
        else if (cls.capturevideo.active)
                SCR_CaptureVideo_EndVideo();
 }
+#endif
 
 /*
 ===============
@@ -2000,7 +2059,7 @@ qboolean SCR_ScreenShot(char *filename, unsigned char *buffer1, unsigned char *b
 //=============================================================================
 
 int scr_numtouchscreenareas;
-scr_touchscreenarea_t scr_touchscreenareas[16];
+scr_touchscreenarea_t scr_touchscreenareas[128];
 
 static void SCR_DrawTouchscreenOverlay(void)
 {
@@ -2009,7 +2068,7 @@ static void SCR_DrawTouchscreenOverlay(void)
        cachepic_t *pic;
        for (i = 0, a = scr_touchscreenareas;i < scr_numtouchscreenareas;i++, a++)
        {
-               if (vid_touchscreen_outlinealpha.value > 0 && a->rect[0] >= 0 && a->rect[1] >= 0 && a->rect[2] >= 4 && a->rect[3] >= 4)
+               if (developer.integer && vid_touchscreen_outlinealpha.value > 0 && a->rect[0] >= 0 && a->rect[1] >= 0 && a->rect[2] >= 4 && a->rect[3] >= 4)
                {
                        DrawQ_Fill(a->rect[0] +              2, a->rect[1]                 , a->rect[2] - 4,          1    , 1, 1, 1, vid_touchscreen_outlinealpha.value * (0.5f + 0.5f * a->active), 0);
                        DrawQ_Fill(a->rect[0] +              1, a->rect[1] +              1, a->rect[2] - 2,          1    , 1, 1, 1, vid_touchscreen_outlinealpha.value * (0.5f + 0.5f * a->active), 0);
@@ -2021,14 +2080,23 @@ static void SCR_DrawTouchscreenOverlay(void)
                pic = a->pic ? Draw_CachePic(a->pic) : NULL;
                if (pic && pic->tex != r_texture_notexture)
                        DrawQ_Pic(a->rect[0], a->rect[1], Draw_CachePic(a->pic), a->rect[2], a->rect[3], 1, 1, 1, vid_touchscreen_overlayalpha.value * (0.5f + 0.5f * a->active), 0);
+               if (a->text && a->text[0])
+               {
+                       int textwidth = DrawQ_TextWidth(a->text, 0, a->textheight, a->textheight, false, FONT_CHAT);
+                       DrawQ_String(a->rect[0] + (a->rect[2] - textwidth) * 0.5f, a->rect[1] + (a->rect[3] - a->textheight) * 0.5f, a->text, 0, a->textheight, a->textheight, 1.0f, 1.0f, 1.0f, vid_touchscreen_overlayalpha.value, 0, NULL, false, FONT_CHAT);
+               }
        }
 }
 
 void R_ClearScreen(qboolean fogcolor)
 {
        float clearcolor[4];
-       // clear to black
-       Vector4Clear(clearcolor);
+       if (scr_screenshot_alpha.integer)
+               // clear to transparency (so png screenshots can contain alpha channel, useful for building model pictures)
+               Vector4Set(clearcolor, 0.0f, 0.0f, 0.0f, 0.0f);
+       else
+               // clear to opaque black (if we're being composited it might otherwise render as transparent)
+               Vector4Set(clearcolor, 0.0f, 0.0f, 0.0f, 1.0f);
        if (fogcolor && r_fog_clear.integer)
        {
                R_UpdateFog();
@@ -2121,7 +2189,7 @@ static void SCR_DrawScreen (void)
                r_refdef.view.ortho_x = atan(r_refdef.view.frustum_x) * (360.0 / M_PI); // abused as angle by VM_CL_R_SetView
                r_refdef.view.ortho_y = atan(r_refdef.view.frustum_y) * (360.0 / M_PI); // abused as angle by VM_CL_R_SetView
 
-               if(!CL_VM_UpdateView())
+               if(!CL_VM_UpdateView(r_stereo_side ? 0.0 : max(0.0, cl.time - cl.oldtime)))
                        R_RenderView();
        }
 
@@ -2184,7 +2252,9 @@ static void SCR_DrawScreen (void)
                SCR_CheckDrawCenterString();
        }
        SCR_DrawNetGraph ();
+#ifdef CONFIG_MENU
        MR_Draw();
+#endif
        CL_DrawVideo();
        R_Shadow_EditLights_DrawSelectedLightProperties();
 
@@ -2569,7 +2639,7 @@ void SCR_UpdateLoadingScreen (qboolean clear, qboolean startup)
        if (qglDrawBuffer)
                qglDrawBuffer(GL_BACK);
        SCR_DrawLoadingScreen_SharedSetup(clear);
-       if (vid.stereobuffer)
+       if (vid.stereobuffer && qglDrawBuffer)
        {
                qglDrawBuffer(GL_BACK_LEFT);
                SCR_DrawLoadingScreen(clear);
@@ -2700,7 +2770,7 @@ void CL_UpdateScreen(void)
 
        loadingscreendone = false;
 
-       if(gamemode == GAME_NEXUIZ || gamemode == GAME_XONOTIC)
+       if(IS_NEXUIZ_DERIVED(gamemode))
        {
                // play a bit with the palette (experimental)
                palette_rgb_pantscolormap[15][0] = (unsigned char) (128 + 127 * sin(cl.time / exp(1.0f) + 0.0f*M_PI/3.0f));
@@ -2751,6 +2821,9 @@ void CL_UpdateScreen(void)
                        sb_lines = 24+16+8;
        }
 
+       R_FrameData_NewFrame();
+       R_BufferData_NewFrame();
+
        Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, vieworigin);
        R_HDR_UpdateIrisAdaptation(vieworigin);
 
@@ -2851,12 +2924,18 @@ void CL_UpdateScreen(void)
                        qglDrawBuffer(GL_BACK_LEFT);
 
                SCR_DrawScreen();
+               r_stereo_side = 0;
        }
        else
 #endif
+       {
+               r_stereo_side = 0;
                SCR_DrawScreen();
+       }
 
+#ifdef CONFIG_VIDEO_CAPTURE
        SCR_CaptureVideo();
+#endif
 
        if (qglFlush)
                qglFlush(); // FIXME: should we really be using qglFlush here?