]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_screen.c
Add GL_ExtensionSupported in vid_null.c because vid_shared.c relies on
[xonotic/darkplaces.git] / cl_screen.c
index bf562e0cd576b25f43464ccefca403855646a779..d6ba9bb831692527c6056b5cc3c00c9235bc317f 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,14 +29,16 @@ 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"};
 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","0", "speed of intermission printing (episode end texts), a value of 0 disables the slow printing"};
-cvar_t scr_loadingscreen_background = {0, "scr_loadingscreen_background","0", "show the last visible background during loading screen (costs one screenful of video memory)"};
+cvar_t scr_loadingscreen_background = {0, "scr_loadingscreen_background","1", "show the last visible background during loading screen (costs one screenful of video memory)"};
 cvar_t scr_loadingscreen_scale = {0, "scr_loadingscreen_scale","1", "scale factor of the background"};
 cvar_t scr_loadingscreen_scale_base = {0, "scr_loadingscreen_scale_base","0", "0 = console pixels, 1 = video pixels"};
 cvar_t scr_loadingscreen_scale_limit = {0, "scr_loadingscreen_scale_limit","0", "0 = no limit, 1 = until first edge hits screen edge, 2 = until last edge hits screen edge, 3 = until width hits screen width, 4 = until height hits screen height"};
@@ -52,10 +56,10 @@ cvar_t scr_screenshot_jpeg = {CVAR_SAVE, "scr_screenshot_jpeg","1", "save jpeg i
 cvar_t scr_screenshot_jpeg_quality = {CVAR_SAVE, "scr_screenshot_jpeg_quality","0.9", "image quality of saved jpeg"};
 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 +71,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)"};
@@ -102,13 +107,13 @@ cvar_t r_speeds_graph_x = {CVAR_SAVE, "r_speeds_graph_x", "0", "position of grap
 cvar_t r_speeds_graph_y = {CVAR_SAVE, "r_speeds_graph_y", "0", "position of graph"};
 cvar_t r_speeds_graph_width = {CVAR_SAVE, "r_speeds_graph_width", "256", "size of graph"};
 cvar_t r_speeds_graph_height = {CVAR_SAVE, "r_speeds_graph_height", "128", "size of graph"};
+cvar_t r_speeds_graph_maxtimedelta = {CVAR_SAVE, "r_speeds_graph_maxtimedelta", "16667", "maximum timedelta to display in the graph (this value will be the top line)"};
+cvar_t r_speeds_graph_maxdefault = {CVAR_SAVE, "r_speeds_graph_maxdefault", "100", "if the minimum and maximum observed values are closer than this, use this value as the graph range (keeps small numbers from being big graphs)"};
 
 
 
-extern cvar_t v_glslgamma;
 extern cvar_t sbar_info_pos;
 extern cvar_t r_fog_clear;
-#define WANT_SCREENSHOT_HWGAMMA (scr_screenshot_hwgamma.integer && vid_usinghwgamma)
 
 int jpeg_supported = false;
 
@@ -247,14 +252,12 @@ static void SCR_CheckDrawCenterString (void)
 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 j, x, y;
        int totalbytes = 0;
        char bytesstring[128];
        float g[NETGRAPH_PACKETS][7];
        float *a;
        float *b;
-       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
        memset(g, 0, sizeof(g));
@@ -294,38 +297,18 @@ static void SCR_DrawNetGraph_DrawGraph (int graphx, int graphy, int graphwidth,
                g[j][6] = bound(0.0f, g[j][6], 1.0f);
        }
        // render the lines for the graph
-       numlines = 0;
-       v = vertex;
        for (j = 0;j < NETGRAPH_PACKETS;j++)
        {
                a = g[j];
                b = g[(j+1)%NETGRAPH_PACKETS];
                if (a[0] < 0.0f || b[0] > 1.0f || b[0] < a[0])
                        continue;
-               VectorSet(v->vertex3f, graphx + graphwidth * a[0], graphy + graphheight * a[2], 0.0f);Vector4Set(v->color4f, 1.0f, 1.0f, 0.0f, 1.0f);Vector2Set(v->texcoord2f, 0.0f, 0.0f);v++;
-               VectorSet(v->vertex3f, graphx + graphwidth * b[0], graphy + graphheight * b[2], 0.0f);Vector4Set(v->color4f, 1.0f, 1.0f, 0.0f, 1.0f);Vector2Set(v->texcoord2f, 0.0f, 0.0f);v++;
-
-               VectorSet(v->vertex3f, graphx + graphwidth * a[0], graphy + graphheight * a[1], 0.0f);Vector4Set(v->color4f, 1.0f, 0.0f, 0.0f, 1.0f);Vector2Set(v->texcoord2f, 0.0f, 0.0f);v++;
-               VectorSet(v->vertex3f, graphx + graphwidth * b[0], graphy + graphheight * b[1], 0.0f);Vector4Set(v->color4f, 1.0f, 0.0f, 0.0f, 1.0f);Vector2Set(v->texcoord2f, 0.0f, 0.0f);v++;
-
-               VectorSet(v->vertex3f, graphx + graphwidth * a[0], graphy + graphheight * a[5], 0.0f);Vector4Set(v->color4f, 0.0f, 1.0f, 0.0f, 1.0f);Vector2Set(v->texcoord2f, 0.0f, 0.0f);v++;
-               VectorSet(v->vertex3f, graphx + graphwidth * b[0], graphy + graphheight * b[5], 0.0f);Vector4Set(v->color4f, 0.0f, 1.0f, 0.0f, 1.0f);Vector2Set(v->texcoord2f, 0.0f, 0.0f);v++;
-
-               VectorSet(v->vertex3f, graphx + graphwidth * a[0], graphy + graphheight * a[4], 0.0f);Vector4Set(v->color4f, 1.0f, 1.0f, 1.0f, 1.0f);Vector2Set(v->texcoord2f, 0.0f, 0.0f);v++;
-               VectorSet(v->vertex3f, graphx + graphwidth * b[0], graphy + graphheight * b[4], 0.0f);Vector4Set(v->color4f, 1.0f, 1.0f, 1.0f, 1.0f);Vector2Set(v->texcoord2f, 0.0f, 0.0f);v++;
-
-               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++;
-
-               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, 0);
-               DrawQ_Lines(0.0f, numlines, 0, false);
+               DrawQ_Line(1, graphx + graphwidth * a[0], graphy + graphheight * a[2], graphx + graphwidth * b[0], graphy + graphheight * b[2], 1.0f, 1.0f, 1.0f, 1.0f, 0);
+               DrawQ_Line(1, graphx + graphwidth * a[0], graphy + graphheight * a[1], graphx + graphwidth * b[0], graphy + graphheight * b[1], 1.0f, 0.0f, 0.0f, 1.0f, 0);
+               DrawQ_Line(1, graphx + graphwidth * a[0], graphy + graphheight * a[5], graphx + graphwidth * b[0], graphy + graphheight * b[5], 0.0f, 1.0f, 0.0f, 1.0f, 0);
+               DrawQ_Line(1, graphx + graphwidth * a[0], graphy + graphheight * a[4], graphx + graphwidth * b[0], graphy + graphheight * b[4], 1.0f, 1.0f, 1.0f, 1.0f, 0);
+               DrawQ_Line(1, graphx + graphwidth * a[0], graphy + graphheight * a[3], graphx + graphwidth * b[0], graphy + graphheight * b[3], 1.0f, 0.5f, 0.0f, 1.0f, 0);
+               DrawQ_Line(1, graphx + graphwidth * a[0], graphy + graphheight * a[6], graphx + graphwidth * b[0], graphy + graphheight * b[6], 0.0f, 0.0f, 1.0f, 1.0f, 0);
        }
        x = graphx;
        y = graphy + graphheight;
@@ -452,7 +435,7 @@ static void SCR_DrawPause (void)
                return;
 
        pic = Draw_CachePic ("gfx/pause");
-       DrawQ_Pic ((vid_conwidth.integer - pic->width)/2, (vid_conheight.integer - pic->height)/2, pic, 0, 0, 1, 1, 1, 1, 0);
+       DrawQ_Pic ((vid_conwidth.integer - Draw_GetPicWidth(pic))/2, (vid_conheight.integer - Draw_GetPicHeight(pic))/2, pic, 0, 0, 1, 1, 1, 1, 0);
 }
 
 /*
@@ -474,26 +457,26 @@ static void SCR_DrawBrand (void)
        {
        case 1: // bottom left
                x = 0;
-               y = vid_conheight.integer - pic->height;
+               y = vid_conheight.integer - Draw_GetPicHeight(pic);
                break;
        case 2: // bottom centre
-               x = (vid_conwidth.integer - pic->width) / 2;
-               y = vid_conheight.integer - pic->height;
+               x = (vid_conwidth.integer - Draw_GetPicWidth(pic)) / 2;
+               y = vid_conheight.integer - Draw_GetPicHeight(pic);
                break;
        case 3: // bottom right
-               x = vid_conwidth.integer - pic->width;
-               y = vid_conheight.integer - pic->height;
+               x = vid_conwidth.integer - Draw_GetPicWidth(pic);
+               y = vid_conheight.integer - Draw_GetPicHeight(pic);
                break;
        case 4: // centre right
-               x = vid_conwidth.integer - pic->width;
-               y = (vid_conheight.integer - pic->height) / 2;
+               x = vid_conwidth.integer - Draw_GetPicWidth(pic);
+               y = (vid_conheight.integer - Draw_GetPicHeight(pic)) / 2;
                break;
        case 5: // top right
-               x = vid_conwidth.integer - pic->width;
+               x = vid_conwidth.integer - Draw_GetPicWidth(pic);
                y = 0;
                break;
        case 6: // top centre
-               x = (vid_conwidth.integer - pic->width) / 2;
+               x = (vid_conwidth.integer - Draw_GetPicWidth(pic)) / 2;
                y = 0;
                break;
        case 7: // top left
@@ -502,7 +485,7 @@ static void SCR_DrawBrand (void)
                break;
        case 8: // centre left
                x = 0;
-               y = (vid_conheight.integer - pic->height) / 2;
+               y = (vid_conheight.integer - Draw_GetPicHeight(pic)) / 2;
                break;
        default:
                return;
@@ -688,10 +671,13 @@ static void SCR_SetUpToDrawConsole (void)
 {
        // lines of console to display
        float conlines;
+#ifdef CONFIG_MENU
        static int framecounter = 0;
+#endif
 
        Con_CheckResize ();
 
+#ifdef CONFIG_MENU
        if (scr_menuforcewhiledisconnected.integer && key_dest == key_game && cls.state == ca_disconnected)
        {
                if (framecounter >= 2)
@@ -701,6 +687,7 @@ static void SCR_SetUpToDrawConsole (void)
        }
        else
                framecounter = 0;
+#endif
 
        if (scr_conforcewhiledisconnected.integer && key_dest == key_game && cls.signon != SIGNONS)
                key_consoleactive |= KEY_CONSOLEACTIVE_FORCED;
@@ -790,6 +777,8 @@ const char *r_stat_name[r_stat_count] =
        "bloom",
        "bloom_copypixels",
        "bloom_drawpixels",
+       "rendertargets_used",
+       "rendertargets_pixels",
        "indexbufferuploadcount",
        "indexbufferuploadsize",
        "vertexbufferuploadcount",
@@ -804,9 +793,6 @@ const char *r_stat_name[r_stat_count] =
        "bufferdatasize_index16",
        "bufferdatasize_index32",
        "bufferdatasize_uniform",
-       "animcache_vertexmesh_count",
-       "animcache_vertexmesh_vertices",
-       "animcache_vertexmesh_maxvertices",
        "animcache_skeletal_count",
        "animcache_skeletal_bones",
        "animcache_skeletal_maxbones",
@@ -885,10 +871,6 @@ const char *r_stat_name[r_stat_count] =
        "dynamic_surfaces_because_tcmod_turbulent",
        "dynamic_vertices_because_tcmod_turbulent",
        "dynamic_triangles_because_tcmod_turbulent",
-       "dynamic_batches_because_interleavedarrays",
-       "dynamic_surfaces_because_interleavedarrays",
-       "dynamic_vertices_because_interleavedarrays",
-       "dynamic_triangles_because_interleavedarrays",
        "dynamic_batches_because_nogaps",
        "dynamic_surfaces_because_nogaps",
        "dynamic_vertices_because_nogaps",
@@ -942,7 +924,8 @@ void R_TimeReport(const char *desc)
        t = (int) ((r_timereport_current - r_timereport_temp) * 1000000.0 + 0.5);
 
        length = dpsnprintf(tempbuf, sizeof(tempbuf), "%8i %s", t, desc);
-       length = min(length, (int)sizeof(tempbuf) - 1);
+       if (length < 0)
+               length = (int)sizeof(tempbuf) - 1;
        if (r_speeds_longestitem < length)
                r_speeds_longestitem = length;
        for (;length < r_speeds_longestitem;length++)
@@ -988,7 +971,7 @@ extern cvar_t r_viewscale;
 extern float viewscalefpsadjusted;
 static void R_TimeReport_EndFrame(void)
 {
-       int i, j, lines, y;
+       int j, lines;
        cl_locnode_t *loc;
        char string[1024+4096];
        mleaf_t *viewleaf;
@@ -1016,6 +999,7 @@ static void R_TimeReport_EndFrame(void)
 "bouncegrid:%4i lights%6i particles%6i traces%6i hits%6i splats%6i bounces\n"
 "photon cache efficiency:%6i cached%6i traced%6ianimated\n"
 "%6i draws%8i vertices%8i triangles bloompixels%8i copied%8i drawn\n"
+"%3i rendertargets%8i pixels\n"
 "updated%5i indexbuffers%8i bytes%5i vertexbuffers%8i bytes\n"
 "animcache%5ib gpuskeletal%7i vertices (%7i with normals)\n"
 "fastbatch%5i count%5i surfaces%7i vertices %7i triangles\n"
@@ -1032,6 +1016,7 @@ static void R_TimeReport_EndFrame(void)
 , r_refdef.stats[r_stat_bouncegrid_lights], r_refdef.stats[r_stat_bouncegrid_particles], r_refdef.stats[r_stat_bouncegrid_traces], r_refdef.stats[r_stat_bouncegrid_hits], r_refdef.stats[r_stat_bouncegrid_splats], r_refdef.stats[r_stat_bouncegrid_bounces]
 , r_refdef.stats[r_stat_photoncache_cached], r_refdef.stats[r_stat_photoncache_traced], r_refdef.stats[r_stat_photoncache_animated]
 , r_refdef.stats[r_stat_draws], r_refdef.stats[r_stat_draws_vertices], r_refdef.stats[r_stat_draws_elements] / 3, r_refdef.stats[r_stat_bloom_copypixels], r_refdef.stats[r_stat_bloom_drawpixels]
+, r_refdef.stats[r_stat_rendertargets_used], r_refdef.stats[r_stat_rendertargets_pixels]
 , r_refdef.stats[r_stat_indexbufferuploadcount], r_refdef.stats[r_stat_indexbufferuploadsize], r_refdef.stats[r_stat_vertexbufferuploadcount], r_refdef.stats[r_stat_vertexbufferuploadsize]
 , r_refdef.stats[r_stat_animcache_skeletal_bones], r_refdef.stats[r_stat_animcache_shape_vertices], r_refdef.stats[r_stat_animcache_shade_vertices]
 , r_refdef.stats[r_stat_batch_fast_batches], r_refdef.stats[r_stat_batch_fast_surfaces], r_refdef.stats[r_stat_batch_fast_vertices], r_refdef.stats[r_stat_batch_fast_triangles]
@@ -1052,6 +1037,7 @@ static void R_TimeReport_EndFrame(void)
 
        if (string[0])
        {
+               int i, y;
                if (string[strlen(string)-1] == '\n')
                        string[strlen(string)-1] = 0;
                lines = 1;
@@ -1083,12 +1069,13 @@ static void R_TimeReport_EndFrame(void)
        if (r_speeds_graph.integer)
        {
                // if we currently have no graph data, reset the graph data entirely
+               int i;
                if (!cls.r_speeds_graph_data)
                        for (i = 0;i < r_stat_count;i++)
-                               cls.r_speeds_graph_datamin[i] = cls.r_speeds_graph_datamax[i] = r_refdef.stats[i];
+                               cls.r_speeds_graph_datamin[i] = cls.r_speeds_graph_datamax[i] = 0;
                if (cls.r_speeds_graph_length != r_speeds_graph_length.integer)
                {
-                       int i, stat, index, d, graph_length, *graph_data;
+                       int stat, index, d, graph_length, *graph_data;
                        cls.r_speeds_graph_length = r_speeds_graph_length.integer;
                        cls.r_speeds_graph_current = 0;
                        if (cls.r_speeds_graph_data)
@@ -1122,10 +1109,10 @@ static void R_TimeReport_EndFrame(void)
        if (cls.r_speeds_graph_length)
        {
                char legend[128];
-               r_vertexgeneric_t *v;
-               int numlines;
+               int i;
                const int *data;
                float x, y, width, height, scalex, scaley;
+               int range_default = max(r_speeds_graph_maxdefault.integer, 1);
                int color, stat, stats, index, range_min, range_max;
                int graph_current, graph_length, *graph_data;
                int statindex[R_SPEEDS_GRAPH_COLORS];
@@ -1202,9 +1189,6 @@ static void R_TimeReport_EndFrame(void)
                        // legend text is drawn after the graphs
                        // render the graph lines, we'll go back and render the legend text later
                        scalex = (float)width / (1000000.0 * r_speeds_graph_seconds.value);
-                       // get space in a vertex buffer to draw this
-                       numlines = stats * (graph_length - 1);
-                       v = R_Mesh_PrepareVertices_Generic_Lock(numlines * 2);
                        stats = 0;
                        for (color = 0;color < R_SPEEDS_GRAPH_COLORS;color++)
                        {
@@ -1214,13 +1198,11 @@ static void R_TimeReport_EndFrame(void)
                                        continue;
                                // prefer to graph stats with 0 base, but if they are
                                // negative we have no choice
-                               range_min = min(cls.r_speeds_graph_datamin[stat], 0);
-                               range_max = cls.r_speeds_graph_datamax[stat];
+                               range_min = cls.r_speeds_graph_datamin[stat];
+                               range_max = max(cls.r_speeds_graph_datamax[stat], range_min + range_default);
                                // some stats we specifically override the graph scale on
                                if (stat == r_stat_timedelta)
-                                       range_max = 100000;
-                               if (range_max == range_min)
-                                       range_max++;
+                                       range_max = r_speeds_graph_maxtimedelta.integer;
                                scaley = height / (range_max - range_min);
                                // generate lines (2 vertices each)
                                // to deal with incomplete data we walk right to left
@@ -1229,39 +1211,19 @@ static void R_TimeReport_EndFrame(void)
                                sum = 0;
                                for (i = 0;i < graph_length - 1;)
                                {
-                                       v->vertex3f[0] = x + width - sum * scalex;
-                                       if (v->vertex3f[0] < x)
-                                               v->vertex3f[0] = x;
-                                       v->vertex3f[1] = y + height - (data[index] - range_min) * scaley;
-                                       v->vertex3f[2] = 0;
-                                       v->color4f[0] = r_speeds_graph_colors[color][0];
-                                       v->color4f[1] = r_speeds_graph_colors[color][1];
-                                       v->color4f[2] = r_speeds_graph_colors[color][2];
-                                       v->color4f[3] = r_speeds_graph_colors[color][3];
-                                       v->texcoord2f[0] = 0;
-                                       v->texcoord2f[1] = 0;
-                                       v++;
+                                       float x1, y1, x2, y2;
+                                       x1 = max(x, x + width - sum * scalex);
+                                       y1 = y + height - (data[index] - range_min) * scaley;
                                        sum += graph_data[r_stat_timedelta * graph_length + index];
                                        index--;
                                        if (index < 0)
                                                index = graph_length - 1;
                                        i++;
-                                       v->vertex3f[0] = x + width - sum * scalex;
-                                       if (v->vertex3f[0] < x)
-                                               v->vertex3f[0] = x;
-                                       v->vertex3f[1] = y + height - (data[index] - range_min) * scaley;
-                                       v->vertex3f[2] = 0;
-                                       v->color4f[0] = r_speeds_graph_colors[color][0];
-                                       v->color4f[1] = r_speeds_graph_colors[color][1];
-                                       v->color4f[2] = r_speeds_graph_colors[color][2];
-                                       v->color4f[3] = r_speeds_graph_colors[color][3];
-                                       v->texcoord2f[0] = 0;
-                                       v->texcoord2f[1] = 0;
-                                       v++;
+                                       x2 = max(x, x + width - sum * scalex);
+                                       y2 = y + height - (data[index] - range_min) * scaley;
+                                       DrawQ_Line(1, x1, y1, x2, y2, r_speeds_graph_colors[color][0], r_speeds_graph_colors[color][1], r_speeds_graph_colors[color][2], r_speeds_graph_colors[color][3], 0);
                                }
                        }
-                       R_Mesh_PrepareVertices_Generic_Unlock();
-                       DrawQ_Lines(0.0f, numlines, 0, false);
                }
 
                // return to not drawing anything if r_render is 0
@@ -1296,10 +1258,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)
@@ -1319,7 +1285,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);
@@ -1344,10 +1312,10 @@ void CL_Screen_Init(void)
        Cvar_RegisterVariable (&scr_screenshot_jpeg_quality);
        Cvar_RegisterVariable (&scr_screenshot_png);
        Cvar_RegisterVariable (&scr_screenshot_gammaboost);
-       Cvar_RegisterVariable (&scr_screenshot_hwgamma);
        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);
@@ -1359,6 +1327,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);
@@ -1384,6 +1353,8 @@ void CL_Screen_Init(void)
        Cvar_RegisterVariable(&r_speeds_graph_y);
        Cvar_RegisterVariable(&r_speeds_graph_width);
        Cvar_RegisterVariable(&r_speeds_graph_height);
+       Cvar_RegisterVariable(&r_speeds_graph_maxtimedelta);
+       Cvar_RegisterVariable(&r_speeds_graph_maxdefault);
 
        // if we want no console, turn it off here too
        if (COM_CheckParm ("-noconsole"))
@@ -1395,7 +1366,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;
 }
@@ -1523,6 +1496,7 @@ void SCR_ScreenShot_f (void)
        Mem_Free (buffer2);
 }
 
+#ifdef CONFIG_VIDEO_CAPTURE
 static void SCR_CaptureVideo_BeginVideo(void)
 {
        double r, g, b;
@@ -1584,17 +1558,10 @@ Cb = R * -.169 + G * -.332 + B *  .500 + 128.;
 Cr = R *  .500 + G * -.419 + B * -.0813 + 128.;
 */
 
-       if(WANT_SCREENSHOT_HWGAMMA)
-       {
-               VID_BuildGammaTables(&cls.capturevideo.vidramp[0], 256);
-       }
-       else
-       {
-               // identity gamma table
-               BuildGammaTable16(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, cls.capturevideo.vidramp, 256);
-               BuildGammaTable16(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, cls.capturevideo.vidramp + 256, 256);
-               BuildGammaTable16(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, cls.capturevideo.vidramp + 256*2, 256);
-       }
+       // identity gamma table
+       BuildGammaTable16(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, cls.capturevideo.vidramp, 256);
+       BuildGammaTable16(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, cls.capturevideo.vidramp + 256, 256);
+       BuildGammaTable16(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, cls.capturevideo.vidramp + 256*2, 256);
        if(scr_screenshot_gammaboost.value != 1)
        {
                double igamma = 1 / scr_screenshot_gammaboost.value;
@@ -1752,7 +1719,7 @@ static void SCR_CaptureVideo_VideoFrame(int newframestepframenum)
 
 void SCR_CaptureVideo_SoundFrame(const portable_sampleframe_t *paintbuffer, size_t length)
 {
-       cls.capturevideo.soundsampleframe += length;
+       cls.capturevideo.soundsampleframe += (int)length;
        cls.capturevideo.soundframe(paintbuffer, length);
 }
 
@@ -1799,6 +1766,7 @@ static void SCR_CaptureVideo(void)
        else if (cls.capturevideo.active)
                SCR_CaptureVideo_EndVideo();
 }
+#endif
 
 /*
 ===============
@@ -1836,6 +1804,7 @@ static void R_Envmap_f (void)
        char filename[MAX_QPATH], basename[MAX_QPATH];
        unsigned char *buffer1;
        unsigned char *buffer2;
+       r_rendertarget_t *rt;
 
        if (Cmd_Argc() != 3)
        {
@@ -1868,6 +1837,7 @@ static void R_Envmap_f (void)
        r_refdef.view.depth = 1;
        r_refdef.view.useperspective = true;
        r_refdef.view.isoverlay = false;
+       r_refdef.view.ismain = true;
 
        r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
        r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
@@ -1877,6 +1847,9 @@ static void R_Envmap_f (void)
        buffer1 = (unsigned char *)Mem_Alloc(tempmempool, size * size * 4);
        buffer2 = (unsigned char *)Mem_Alloc(tempmempool, size * size * 3);
 
+       // TODO: use TEXTYPE_COLORBUFFER16F and output to .exr files as well?
+       rt = R_RenderTarget_Get(size, size, TEXTYPE_DEPTHBUFFER24STENCIL8, true, TEXTYPE_COLORBUFFER, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
+       CL_UpdateEntityShading();
        for (j = 0;j < 12;j++)
        {
                dpsnprintf(filename, sizeof(filename), "env/%s%s.tga", basename, envmapinfo[j].name);
@@ -1884,7 +1857,7 @@ static void R_Envmap_f (void)
                r_refdef.view.quality = 1;
                r_refdef.view.clear = true;
                R_Mesh_Start();
-               R_RenderView();
+               R_RenderView(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, size, size);
                R_Mesh_Finish();
                SCR_ScreenShot(filename, buffer1, buffer2, 0, vid.height - (r_refdef.view.y + r_refdef.view.height), size, size, envmapinfo[j].flipx, envmapinfo[j].flipy, envmapinfo[j].flipdiagonaly, false, false, false, false);
        }
@@ -1932,10 +1905,12 @@ void SHOWLMP_decodeshow(void)
                showlmp_t *oldshowlmps = cl.showlmps;
                cl.max_showlmps += 16;
                cl.showlmps = (showlmp_t *) Mem_Alloc(cls.levelmempool, cl.max_showlmps * sizeof(showlmp_t));
-               if (cl.num_showlmps)
-                       memcpy(cl.showlmps, oldshowlmps, cl.num_showlmps * sizeof(showlmp_t));
                if (oldshowlmps)
+               {
+                       if (cl.num_showlmps)
+                               memcpy(cl.showlmps, oldshowlmps, cl.num_showlmps * sizeof(showlmp_t));
                        Mem_Free(oldshowlmps);
+               }
        }
        for (k = 0;k < cl.max_showlmps;k++)
                if (cl.showlmps[k].isactive && !strcmp(cl.showlmps[k].label, lmplabel))
@@ -1977,22 +1952,15 @@ qboolean SCR_ScreenShot(char *filename, unsigned char *buffer1, unsigned char *b
 
        GL_ReadPixelsBGRA(x, y, width, height, buffer1);
 
-       if(gammacorrect && (scr_screenshot_gammaboost.value != 1 || WANT_SCREENSHOT_HWGAMMA))
+       if(gammacorrect && (scr_screenshot_gammaboost.value != 1))
        {
                int i;
                double igamma = 1.0 / scr_screenshot_gammaboost.value;
                unsigned short vidramp[256 * 3];
-               if(WANT_SCREENSHOT_HWGAMMA)
-               {
-                       VID_BuildGammaTables(&vidramp[0], 256);
-               }
-               else
-               {
-                       // identity gamma table
-                       BuildGammaTable16(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, vidramp, 256);
-                       BuildGammaTable16(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, vidramp + 256, 256);
-                       BuildGammaTable16(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, vidramp + 256*2, 256);
-               }
+               // identity gamma table
+               BuildGammaTable16(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, vidramp, 256);
+               BuildGammaTable16(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, vidramp + 256, 256);
+               BuildGammaTable16(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, vidramp + 256*2, 256);
                if(scr_screenshot_gammaboost.value != 1)
                {
                        for (i = 0;i < 256 * 3;i++)
@@ -2048,7 +2016,7 @@ static void SCR_DrawTouchscreenOverlay(void)
        cachepic_t *pic;
        for (i = 0, a = scr_touchscreenareas;i < scr_numtouchscreenareas;i++, a++)
        {
-               if (developer.integer && vid_touchscreen_outlinealpha.value > 0 && a->rect[0] >= 0 && a->rect[1] >= 0 && a->rect[2] >= 4 && a->rect[3] >= 4)
+               if (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);
@@ -2057,9 +2025,9 @@ static void SCR_DrawTouchscreenOverlay(void)
                        DrawQ_Fill(a->rect[0] +              1, a->rect[1] + a->rect[3] - 2, a->rect[2] - 2,          1    , 1, 1, 1, vid_touchscreen_outlinealpha.value * (0.5f + 0.5f * a->active), 0);
                        DrawQ_Fill(a->rect[0] +              2, a->rect[1] + a->rect[3] - 1, a->rect[2] - 4,          1    , 1, 1, 1, vid_touchscreen_outlinealpha.value * (0.5f + 0.5f * a->active), 0);
                }
-               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);
+               pic = a->pic ? Draw_CachePic_Flags(a->pic, CACHEPICFLAG_FAILONMISSING) : NULL;
+               if (Draw_IsPicLoaded(pic))
+                       DrawQ_Pic(a->rect[0], a->rect[1], 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);
@@ -2071,22 +2039,25 @@ static void SCR_DrawTouchscreenOverlay(void)
 void R_ClearScreen(qboolean fogcolor)
 {
        float clearcolor[4];
-       // 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 (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();
                VectorCopy(r_refdef.fogcolor, clearcolor);
        }
        // clear depth is 1.0
-       // LordHavoc: we use a stencil centered around 128 instead of 0,
-       // to avoid clamping interfering with strange shadow volume
-       // drawing orders
        // clear the screen
-       GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | (vid.stencil ? GL_STENCIL_BUFFER_BIT : 0), clearcolor, 1.0f, 128);
+       GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | (vid.stencil ? GL_STENCIL_BUFFER_BIT : 0), clearcolor, 1.0f, 0);
 }
 
 int r_stereo_side;
+extern cvar_t v_isometric;
+extern cvar_t v_isometric_verticalfov;
 
 static void SCR_DrawScreen (void)
 {
@@ -2096,6 +2067,10 @@ static void SCR_DrawScreen (void)
 
        R_UpdateVariables();
 
+       // this will be set back to 0 by R_RenderView during CL_VM_UpdateView
+       r_refdef.draw2dstage = 1;
+       R_ResetViewRendering2D_Common(0, NULL, NULL, 0, 0, vid.width, vid.height, vid_conwidth.integer, vid_conheight.integer);
+
        // Quake uses clockwise winding, so these are swapped
        r_refdef.view.cullface_front = GL_BACK;
        r_refdef.view.cullface_back = GL_FRONT;
@@ -2157,7 +2132,7 @@ static void SCR_DrawScreen (void)
                // for a 4x3 display, if the ratio is not 4x3 this makes the fov
                // higher/lower according to the ratio
                r_refdef.view.useperspective = true;
-               r_refdef.view.frustum_y = tan(scr_fov.value * M_PI / 360.0) * (3.0/4.0) * cl.viewzoom;
+               r_refdef.view.frustum_y = tan(scr_fov.value * M_PI / 360.0) * (3.0 / 4.0) * cl.viewzoom;
                r_refdef.view.frustum_x = r_refdef.view.frustum_y * (float)r_refdef.view.width / (float)r_refdef.view.height / vid_pixelheight.value;
 
                r_refdef.view.frustum_x *= r_refdef.frustumscale_x;
@@ -2165,10 +2140,22 @@ 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(r_stereo_side ? 0.0 : max(0.0, cl.time - cl.oldtime)))
-                       R_RenderView();
+               r_refdef.view.ismain = true;
+
+               // if CSQC is loaded, it is required to provide the CSQC_UpdateView function,
+               // and won't render a view if it does not call that.
+               if (cl.csqc_loaded)
+                       CL_VM_UpdateView(r_stereo_side ? 0.0 : max(0.0, cl.time - cl.oldtime));
+               else
+               {
+                       CL_UpdateEntityShading();
+                       R_RenderView(0, NULL, NULL, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
+               }
        }
 
+       // Don't apply debugging stuff like r_showsurfaces to the UI
+       r_refdef.view.showdebug = false;
+
        if (!r_stereo_sidebyside.integer && !r_stereo_horizontal.integer && !r_stereo_vertical.integer)
        {
                r_refdef.view.width = vid.width;
@@ -2228,7 +2215,9 @@ static void SCR_DrawScreen (void)
                SCR_CheckDrawCenterString();
        }
        SCR_DrawNetGraph ();
+#ifdef CONFIG_MENU
        MR_Draw();
+#endif
        CL_DrawVideo();
        R_Shadow_EditLights_DrawSelectedLightProperties();
 
@@ -2249,9 +2238,8 @@ static void SCR_DrawScreen (void)
 
        DrawQ_Finish();
 
-       R_DrawGamma();
-
        R_Mesh_Finish();
+       R_RenderTarget_FreeUnused(false);
 }
 
 typedef struct loadingscreenstack_s
@@ -2288,17 +2276,8 @@ static void SCR_SetLoadingScreenTexture(void)
 
        SCR_ClearLoadingScreenTexture();
 
-       if (vid.support.arb_texture_non_power_of_two)
-       {
-               w = vid.width; h = vid.height;
-               loadingscreentexture_w = loadingscreentexture_h = 1;
-       }
-       else
-       {
-               w = CeilPowerOf2(vid.width); h = CeilPowerOf2(vid.height);
-               loadingscreentexture_w = vid.width / (float) w;
-               loadingscreentexture_h = vid.height / (float) h;
-       }
+       w = vid.width; h = vid.height;
+       loadingscreentexture_w = loadingscreentexture_h = 1;
 
        loadingscreentexture = R_LoadTexture2D(r_main_texturepool, "loadingscreentexture", w, h, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
        R_Mesh_CopyToTexture(loadingscreentexture, 0, 0, 0, 0, vid.width, vid.height);
@@ -2475,8 +2454,8 @@ static void SCR_DrawLoadingScreen_SharedSetup (qboolean clear)
        // draw the loading plaque
        loadingscreenpic = Draw_CachePic_Flags (loadingscreenpic_number ? va(vabuf, sizeof(vabuf), "%s%d", scr_loadingscreen_picture.string, loadingscreenpic_number+1) : scr_loadingscreen_picture.string, loadingscreenpic_number ? CACHEPICFLAG_NOTPERSISTENT : 0);
 
-       w = loadingscreenpic->width;
-       h = loadingscreenpic->height;
+       w = Draw_GetPicWidth(loadingscreenpic);
+       h = Draw_GetPicHeight(loadingscreenpic);
 
        // apply scale
        w *= scr_loadingscreen_scale.value;
@@ -2539,11 +2518,11 @@ static void SCR_DrawLoadingScreen (qboolean clear)
        if(loadingscreentexture)
        {
                R_Mesh_PrepareVertices_Generic_Arrays(4, loadingscreentexture_vertex3f, NULL, loadingscreentexture_texcoord2f);
-               R_SetupShader_Generic(loadingscreentexture, NULL, GL_MODULATE, 1, true, true, true);
+               R_SetupShader_Generic(loadingscreentexture, false, true, true);
                R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
        }
        R_Mesh_PrepareVertices_Generic_Arrays(4, loadingscreenpic_vertex3f, NULL, loadingscreenpic_texcoord2f);
-       R_SetupShader_Generic(Draw_GetPicTexture(loadingscreenpic), NULL, GL_MODULATE, 1, true, true, false);
+       R_SetupShader_Generic(Draw_GetPicTexture(loadingscreenpic), true, true, false);
        R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
        SCR_DrawLoadingStack();
 }
@@ -2575,6 +2554,10 @@ void SCR_UpdateLoadingScreen (qboolean clear, qboolean startup)
                loadingscreen_lastupdate = t;
        }
 
+       // set up the r_texture_gammaramps texture which we need for rendering the loadingscreenpic
+       VID_UpdateGamma();
+       R_UpdateVariables();
+
        if(!scr_loadingscreen_background.integer)
                clear = true;
        
@@ -2610,10 +2593,9 @@ void SCR_UpdateLoadingScreen (qboolean clear, qboolean startup)
        SCR_DrawLoadingScreen_SharedSetup(clear);
        SCR_DrawLoadingScreen(clear);
 #else
-       if (qglDrawBuffer)
-               qglDrawBuffer(GL_BACK);
+       qglDrawBuffer(GL_BACK);
        SCR_DrawLoadingScreen_SharedSetup(clear);
-       if (vid.stereobuffer && qglDrawBuffer)
+       if (vid.stereobuffer)
        {
                qglDrawBuffer(GL_BACK_LEFT);
                SCR_DrawLoadingScreen(clear);
@@ -2622,8 +2604,7 @@ void SCR_UpdateLoadingScreen (qboolean clear, qboolean startup)
        }
        else
        {
-               if (qglDrawBuffer)
-                       qglDrawBuffer(GL_BACK);
+               qglDrawBuffer(GL_BACK);
                SCR_DrawLoadingScreen(clear);
        }
 #endif
@@ -2744,7 +2725,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));
@@ -2808,20 +2789,8 @@ void CL_UpdateScreen(void)
        SCR_SetUpToDrawConsole();
 
 #ifndef USE_GLES2
-       if (qglDrawBuffer)
-       {
-               CHECKGLERROR
-               qglDrawBuffer(GL_BACK);CHECKGLERROR
-               // set dithering mode
-               if (gl_dither.integer)
-               {
-                       qglEnable(GL_DITHER);CHECKGLERROR
-               }
-               else
-               {
-                       qglDisable(GL_DITHER);CHECKGLERROR
-               }
-       }
+       CHECKGLERROR
+       qglDrawBuffer(GL_BACK);CHECKGLERROR
 #endif
 
        R_Viewport_InitOrtho(&viewport, &identitymatrix, 0, 0, vid.width, vid.height, 0, 0, vid_conwidth.integer, vid_conheight.integer, -10, 100, NULL);
@@ -2838,34 +2807,11 @@ void CL_UpdateScreen(void)
        // calculate r_refdef.view.quality
        r_refdef.view.quality = cl_updatescreen_quality;
 
-#ifndef USE_GLES2
-       if (qglPolygonStipple)
+       if(scr_stipple.integer)
        {
-               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);CHECKGLERROR // 0x0B42
-                       for(i = 0; i < 128; ++i)
-                       {
-                               int line = i/4;
-                               stipple[i] = (((line >> width) + frame) & ((1 << parts) - 1)) ? 0x00 : 0xFF;
-                       }
-                       qglPolygonStipple(stipple);CHECKGLERROR
-               }
-               else
-               {
-                       qglDisable(GL_POLYGON_STIPPLE);CHECKGLERROR
-               }
+               Con_Print("FIXME: scr_stipple not implemented\n");
+               Cvar_SetValueQuick(&scr_stipple, 0);
        }
-#endif
 
 #ifndef USE_GLES2
        if (R_Stereo_Active())
@@ -2907,10 +2853,11 @@ void CL_UpdateScreen(void)
                SCR_DrawScreen();
        }
 
+#ifdef CONFIG_VIDEO_CAPTURE
        SCR_CaptureVideo();
+#endif
 
-       if (qglFlush)
-               qglFlush(); // FIXME: should we really be using qglFlush here?
+       qglFlush(); // ensure that the commands are submitted to the GPU before we do other things
 
        if (!vid_activewindow)
                VID_SetMouse(false, false, false);