]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_screen.c
renamed IN_Activate to VID_GrabMouse and made it a public function in
[xonotic/darkplaces.git] / cl_screen.c
index 7eb8bf880c9eb27fb2f8edb07a01c2b8a192e5ff..a46093d2f14e455183369002fcf4f4bfcb60d547 100644 (file)
@@ -32,7 +32,7 @@ cvar_t scr_screenshot_gammaboost = {CVAR_SAVE, "scr_screenshot_gammaboost","1",
 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_width = {0, "cl_capturevideo_width", "0", "scales all frames to this resolution before saving the video"};
 cvar_t cl_capturevideo_height = {0, "cl_capturevideo_height", "0", "scales all frames to this resolution before saving the video"};
-cvar_t cl_capturevideo_realtime = {0, "cl_capturevideo_realtime", "0", "causes video saving to operate in realtime (mostly useful while playing, not while capturing demos), this can produce a much lower quality video due to poor sound/video sync and will abort saving if your machine stalls for over 1 second"};
+cvar_t cl_capturevideo_realtime = {0, "cl_capturevideo_realtime", "0", "causes video saving to operate in realtime (mostly useful while playing, not while capturing demos), this can produce a much lower quality video due to poor sound/video sync and will abort saving if your machine stalls for over a minute"};
 cvar_t cl_capturevideo_fps = {0, "cl_capturevideo_fps", "30", "how many frames per second to save (29.97 for NTSC, 30 for typical PC video, 15 can be useful)"};
 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 r_letterbox = {0, "r_letterbox", "0", "reduces vertical height of view to simulate a letterboxed movie effect (can be used by mods for cutscenes)"};
@@ -118,6 +118,9 @@ void SCR_DrawCenterString (void)
                if(sb_showscores) // make TAB hide the finale message (sb_showscores overrides finale in sbar.c)
                        return;
 
+       if(scr_centertime.value <= 0 && !cl.intermission)
+               return;
+
 // 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));
@@ -334,7 +337,7 @@ void SCR_DrawTurtle (void)
        if (count < 3)
                return;
 
-       DrawQ_Pic (0, 0, Draw_CachePic("gfx/turtle", true), 0, 0, 1, 1, 1, 1, 0);
+       DrawQ_Pic (0, 0, Draw_CachePic ("gfx/turtle"), 0, 0, 1, 1, 1, 1, 0);
 }
 
 /*
@@ -351,7 +354,7 @@ void SCR_DrawNet (void)
        if (cls.demoplayback)
                return;
 
-       DrawQ_Pic (64, 0, Draw_CachePic("gfx/net", true), 0, 0, 1, 1, 1, 1, 0);
+       DrawQ_Pic (64, 0, Draw_CachePic ("gfx/net"), 0, 0, 1, 1, 1, 1, 0);
 }
 
 /*
@@ -372,7 +375,7 @@ void SCR_DrawPause (void)
        if (!cl.paused)
                return;
 
-       pic = Draw_CachePic ("gfx/pause", true);
+       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);
 }
 
@@ -389,7 +392,7 @@ void SCR_DrawBrand (void)
        if (!scr_showbrand.value)
                return;
 
-       pic = Draw_CachePic ("gfx/brand", true);
+       pic = Draw_CachePic ("gfx/brand");
 
        switch ((int)scr_showbrand.value)
        {
@@ -629,7 +632,7 @@ void SCR_BeginLoadingPlaque (void)
 
 //=============================================================================
 
-char r_speeds_timestring[1024];
+char r_speeds_timestring[4096];
 int speedstringcount, r_timereport_active;
 double r_timereport_temp = 0, r_timereport_current = 0, r_timereport_start = 0;
 int r_speeds_longestitem = 0;
@@ -686,7 +689,7 @@ void R_TimeReport_EndFrame(void)
 {
        int i, j, lines, y;
        cl_locnode_t *loc;
-       char string[2048];
+       char string[1024+4096];
 
        string[0] = 0;
        if (r_speeds.integer && cls.signon == SIGNONS && cls.state == ca_connected)
@@ -696,9 +699,9 @@ void R_TimeReport_EndFrame(void)
                loc = CL_Locs_FindNearest(cl.movement_origin);
                if (loc)
                        sprintf(string + strlen(string), "Location: %s\n", loc->name);
-               sprintf(string + strlen(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(string + strlen(string), "%3i renders org:'%+8.2f %+8.2f %+8.2f' dir:'%+2.3f %+2.3f %+2.3f'\n", r_refdef.stats.renders, r_refdef.view.origin[0], r_refdef.view.origin[1], r_refdef.view.origin[2], r_refdef.view.forward[0], r_refdef.view.forward[1], r_refdef.view.forward[2]);
                sprintf(string + strlen(string), "%7i surfaces%7i triangles %5i entities (%7i surfaces%7i triangles)\n", r_refdef.stats.world_surfaces, r_refdef.stats.world_triangles, r_refdef.stats.entities, r_refdef.stats.entities_surfaces, r_refdef.stats.entities_triangles);
-               sprintf(string + strlen(string), "%5i leafs%5i portals%6i particles%6i decals\n", r_refdef.stats.world_leafs, r_refdef.stats.world_portals, r_refdef.stats.particles, r_refdef.stats.decals);
+               sprintf(string + strlen(string), "%5i leafs%5i portals%6i/%6i particles%6i/%6i decals %3i%% quality\n", r_refdef.stats.world_leafs, r_refdef.stats.world_portals, r_refdef.stats.particles, cl.num_particles, r_refdef.stats.decals, cl.num_decals, (int)(100 * r_refdef.view.quality));
                sprintf(string + strlen(string), "%7i lightmap updates (%7i pixels)\n", r_refdef.stats.lightmapupdates, r_refdef.stats.lightmapupdatepixels);
                sprintf(string + strlen(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);
                if (r_refdef.stats.bloom)
@@ -1631,7 +1634,7 @@ void SCR_CaptureVideo(void)
                else
                        newframenum = cls.capturevideo.frame + 1;
                // if falling behind more than one second, stop
-               if (newframenum - cls.capturevideo.frame > (int)ceil(cls.capturevideo.framerate))
+               if (newframenum - cls.capturevideo.frame > 60 * (int)ceil(cls.capturevideo.framerate))
                {
                        Cvar_SetValueQuick(&cl_capturevideo, 0);
                        Con_Printf("video saving failed on frame %i, your machine is too slow for this capture speed.\n", cls.capturevideo.frame);
@@ -1712,16 +1715,17 @@ static void R_Envmap_f (void)
 
        R_UpdateVariables();
 
-       r_view.x = 0;
-       r_view.y = 0;
-       r_view.z = 0;
-       r_view.width = size;
-       r_view.height = size;
-       r_view.depth = 1;
-       r_view.useperspective = true;
+       r_refdef.view.x = 0;
+       r_refdef.view.y = 0;
+       r_refdef.view.z = 0;
+       r_refdef.view.width = size;
+       r_refdef.view.height = size;
+       r_refdef.view.depth = 1;
+       r_refdef.view.useperspective = true;
+       r_refdef.view.isoverlay = false;
 
-       r_view.frustum_x = tan(90 * M_PI / 360.0);
-       r_view.frustum_y = tan(90 * M_PI / 360.0);
+       r_refdef.view.frustum_x = tan(90 * M_PI / 360.0);
+       r_refdef.view.frustum_y = tan(90 * M_PI / 360.0);
 
        buffer1 = (unsigned char *)Mem_Alloc(tempmempool, size * size * 3);
        buffer2 = (unsigned char *)Mem_Alloc(tempmempool, size * size * 3);
@@ -1730,12 +1734,13 @@ static void R_Envmap_f (void)
        for (j = 0;j < 12;j++)
        {
                sprintf(filename, "env/%s%s.tga", basename, envmapinfo[j].name);
-               Matrix4x4_CreateFromQuakeEntity(&r_view.matrix, r_view.origin[0], r_view.origin[1], r_view.origin[2], envmapinfo[j].angles[0], envmapinfo[j].angles[1], envmapinfo[j].angles[2], 1);
-               r_view.clear = true;
+               Matrix4x4_CreateFromQuakeEntity(&r_refdef.view.matrix, r_refdef.view.origin[0], r_refdef.view.origin[1], r_refdef.view.origin[2], envmapinfo[j].angles[0], envmapinfo[j].angles[1], envmapinfo[j].angles[2], 1);
+               r_refdef.view.quality = 1;
+               r_refdef.view.clear = true;
                R_Mesh_Start();
                R_RenderView();
                R_Mesh_Finish();
-               SCR_ScreenShot(filename, buffer1, buffer2, buffer3, 0, vid.height - (r_view.y + r_view.height), size, size, envmapinfo[j].flipx, envmapinfo[j].flipy, envmapinfo[j].flipdiagonaly, false, false);
+               SCR_ScreenShot(filename, buffer1, buffer2, buffer3, 0, vid.height - (r_refdef.view.y + r_refdef.view.height), size, size, envmapinfo[j].flipx, envmapinfo[j].flipy, envmapinfo[j].flipdiagonaly, false, false);
        }
 
        Mem_Free (buffer1);
@@ -1807,7 +1812,7 @@ void SHOWLMP_drawall(void)
        int i;
        for (i = 0;i < cl.num_showlmps;i++)
                if (cl.showlmps[i].isactive)
-                       DrawQ_Pic(cl.showlmps[i].x, cl.showlmps[i].y, Draw_CachePic(cl.showlmps[i].pic, true), 0, 0, 1, 1, 1, 1, 0);
+                       DrawQ_Pic(cl.showlmps[i].x, cl.showlmps[i].y, Draw_CachePic (cl.showlmps[i].pic), 0, 0, 1, 1, 1, 1, 0);
 }
 
 /*
@@ -1903,8 +1908,8 @@ void SCR_DrawScreen (void)
        R_UpdateVariables();
 
        // Quake uses clockwise winding, so these are swapped
-       r_view.cullface_front = GL_BACK;
-       r_view.cullface_back = GL_FRONT;
+       r_refdef.view.cullface_front = GL_BACK;
+       r_refdef.view.cullface_back = GL_FRONT;
 
        if (cls.signon == SIGNONS)
        {
@@ -1915,23 +1920,23 @@ void SCR_DrawScreen (void)
 
                if (r_stereo_sidebyside.integer)
                {
-                       r_view.width = (int)(vid.width * size / 2.5);
-                       r_view.height = (int)(vid.height * size / 2.5 * (1 - bound(0, r_letterbox.value, 100) / 100));
-                       r_view.depth = 1;
-                       r_view.x = (int)((vid.width - r_view.width * 2.5) * 0.5);
-                       r_view.y = (int)((vid.height - r_view.height)/2);
-                       r_view.z = 0;
+                       r_refdef.view.width = (int)(vid.width * size / 2.5);
+                       r_refdef.view.height = (int)(vid.height * size / 2.5 * (1 - bound(0, r_letterbox.value, 100) / 100));
+                       r_refdef.view.depth = 1;
+                       r_refdef.view.x = (int)((vid.width - r_refdef.view.width * 2.5) * 0.5);
+                       r_refdef.view.y = (int)((vid.height - r_refdef.view.height)/2);
+                       r_refdef.view.z = 0;
                        if (r_stereo_side)
-                               r_view.x += (int)(r_view.width * 1.5);
+                               r_refdef.view.x += (int)(r_refdef.view.width * 1.5);
                }
                else
                {
-                       r_view.width = (int)(vid.width * size);
-                       r_view.height = (int)(vid.height * size * (1 - bound(0, r_letterbox.value, 100) / 100));
-                       r_view.depth = 1;
-                       r_view.x = (int)((vid.width - r_view.width)/2);
-                       r_view.y = (int)((vid.height - r_view.height)/2);
-                       r_view.z = 0;
+                       r_refdef.view.width = (int)(vid.width * size);
+                       r_refdef.view.height = (int)(vid.height * size * (1 - bound(0, r_letterbox.value, 100) / 100));
+                       r_refdef.view.depth = 1;
+                       r_refdef.view.x = (int)((vid.width - r_refdef.view.width)/2);
+                       r_refdef.view.y = (int)((vid.height - r_refdef.view.height)/2);
+                       r_refdef.view.z = 0;
                }
 
                // LordHavoc: viewzoom (zoom in for sniper rifles, etc)
@@ -1940,12 +1945,12 @@ void SCR_DrawScreen (void)
                // this it simply assumes the requested fov is the vertical fov
                // for a 4x3 display, if the ratio is not 4x3 this makes the fov
                // higher/lower according to the ratio
-               r_view.useperspective = true;
-               r_view.frustum_y = tan(scr_fov.value * M_PI / 360.0) * (3.0/4.0) * cl.viewzoom;
-               r_view.frustum_x = r_view.frustum_y * (float)r_view.width / (float)r_view.height / vid_pixelheight.value;
+               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_x = r_refdef.view.frustum_y * (float)r_refdef.view.width / (float)r_refdef.view.height / vid_pixelheight.value;
 
-               r_view.frustum_x *= r_refdef.frustumscale_x;
-               r_view.frustum_y *= r_refdef.frustumscale_y;
+               r_refdef.view.frustum_x *= r_refdef.frustumscale_x;
+               r_refdef.view.frustum_y *= r_refdef.frustumscale_y;
 
                if(!CL_VM_UpdateView())
                        R_RenderView();
@@ -1954,19 +1959,19 @@ void SCR_DrawScreen (void)
                {
                        float sizex = bound(10, scr_zoomwindow_viewsizex.value, 100) / 100.0;
                        float sizey = bound(10, scr_zoomwindow_viewsizey.value, 100) / 100.0;
-                       r_view.width = (int)(vid.width * sizex);
-                       r_view.height = (int)(vid.height * sizey);
-                       r_view.depth = 1;
-                       r_view.x = (int)((vid.width - r_view.width)/2);
-                       r_view.y = 0;
-                       r_view.z = 0;
+                       r_refdef.view.width = (int)(vid.width * sizex);
+                       r_refdef.view.height = (int)(vid.height * sizey);
+                       r_refdef.view.depth = 1;
+                       r_refdef.view.x = (int)((vid.width - r_refdef.view.width)/2);
+                       r_refdef.view.y = 0;
+                       r_refdef.view.z = 0;
 
-                       r_view.useperspective = true;
-                       r_view.frustum_y = tan(scr_zoomwindow_fov.value * M_PI / 360.0) * (3.0/4.0) * cl.viewzoom;
-                       r_view.frustum_x = r_view.frustum_y * vid_pixelheight.value * (float)r_view.width / (float)r_view.height;
+                       r_refdef.view.useperspective = true;
+                       r_refdef.view.frustum_y = tan(scr_zoomwindow_fov.value * M_PI / 360.0) * (3.0/4.0) * cl.viewzoom;
+                       r_refdef.view.frustum_x = r_refdef.view.frustum_y * vid_pixelheight.value * (float)r_refdef.view.width / (float)r_refdef.view.height;
 
-                       r_view.frustum_x *= r_refdef.frustumscale_x;
-                       r_view.frustum_y *= r_refdef.frustumscale_y;
+                       r_refdef.view.frustum_x *= r_refdef.frustumscale_x;
+                       r_refdef.view.frustum_y *= r_refdef.frustumscale_y;
 
                        if(!CL_VM_UpdateView())
                                R_RenderView();
@@ -1975,13 +1980,13 @@ void SCR_DrawScreen (void)
 
        if (!r_stereo_sidebyside.integer)
        {
-               r_view.width = vid.width;
-               r_view.height = vid.height;
-               r_view.depth = 1;
-               r_view.x = 0;
-               r_view.y = 0;
-               r_view.z = 0;
-               r_view.useperspective = false;
+               r_refdef.view.width = vid.width;
+               r_refdef.view.height = vid.height;
+               r_refdef.view.depth = 1;
+               r_refdef.view.x = 0;
+               r_refdef.view.y = 0;
+               r_refdef.view.z = 0;
+               r_refdef.view.useperspective = false;
        }
 
        // draw 2D stuff
@@ -2032,6 +2037,8 @@ void SCR_UpdateLoadingScreen (qboolean clear)
        // don't do anything if not initialized yet
        if (vid_hidden || !scr_refresh.integer)
                return;
+       // release mouse grab while loading
+       VID_GrabMouse(false);
        CHECKGLERROR
        qglViewport(0, 0, vid.width, vid.height);CHECKGLERROR
        //qglDisable(GL_SCISSOR_TEST);CHECKGLERROR
@@ -2050,7 +2057,7 @@ void SCR_UpdateLoadingScreen (qboolean clear)
        R_Mesh_Start();
        R_Mesh_Matrix(&identitymatrix);
        // draw the loading plaque
-       pic = Draw_CachePic("gfx/loading", true);
+       pic = Draw_CachePic ("gfx/loading");
        x = (vid_conwidth.integer - pic->width)/2;
        y = (vid_conheight.integer - pic->height)/2;
        GL_Color(1,1,1,1);
@@ -2063,6 +2070,7 @@ void SCR_UpdateLoadingScreen (qboolean clear)
        R_Mesh_ResetTextureState();
        R_Mesh_TexBind(0, R_GetTexture(pic->tex));
        R_Mesh_TexCoordPointer(0, 2, texcoord2f, 0, 0);
+       R_SetupGenericShader(true);
        vertex3f[2] = vertex3f[5] = vertex3f[8] = vertex3f[11] = 0;
        vertex3f[0] = vertex3f[9] = x;
        vertex3f[1] = vertex3f[4] = y;
@@ -2075,32 +2083,58 @@ void SCR_UpdateLoadingScreen (qboolean clear)
        if (vid.stereobuffer)
        {
                qglDrawBuffer(GL_FRONT_LEFT);
-               R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
+               R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
                qglDrawBuffer(GL_FRONT_RIGHT);
-               R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
+               R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
        }
        else
        {
                qglDrawBuffer(GL_FRONT);
-               R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
+               R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
        }
        R_Mesh_Finish();
        // refresh
        // not necessary when rendering to GL_FRONT buffers
-       //VID_Finish(false);
+       //VID_Finish();
        // however this IS necessary on Windows Vista
        qglFinish();
 }
 
+extern cvar_t cl_minfps;
+extern cvar_t cl_minfps_fade;
+extern cvar_t cl_minfps_qualitymax;
+extern cvar_t cl_minfps_qualitymin;
+extern cvar_t cl_minfps_qualitypower;
+extern cvar_t cl_minfps_qualityscale;
+static double cl_updatescreen_rendertime = 0;
+static double cl_updatescreen_quality = 1;
 void CL_UpdateScreen(void)
 {
+       double rendertime1;
        float conwidth, conheight;
 
+       if (!scr_initialized || !con_initialized)
+               return;                         // not initialized yet
+
+       VID_GrabMouse((vid.fullscreen || (vid_mouse.integer && !key_consoleactive && (key_dest != key_game || !cls.demoplayback))) && vid_activewindow && !cl.csqc_wantsmousemove);
+
+       if(gamemode == GAME_NEXUIZ)
+       {
+               // play a bit with the palette (experimental)
+               palette_rgb_pantscolormap[15][0] = 128 + 127 * sin(cl.time / exp(1) + 0*M_PI/3);
+               palette_rgb_pantscolormap[15][1] = 128 + 127 * sin(cl.time / exp(1) + 2*M_PI/3);
+               palette_rgb_pantscolormap[15][2] = 128 + 127 * sin(cl.time / exp(1) + 4*M_PI/3);
+               palette_rgb_shirtcolormap[15][0] = 128 + 127 * sin(cl.time /  M_PI  + 5*M_PI/3);
+               palette_rgb_shirtcolormap[15][1] = 128 + 127 * sin(cl.time /  M_PI  + 3*M_PI/3);
+               palette_rgb_shirtcolormap[15][2] = 128 + 127 * sin(cl.time /  M_PI  + 1*M_PI/3);
+               memcpy(palette_rgb_pantsscoreboard[15], palette_rgb_pantscolormap[15], sizeof(*palette_rgb_pantscolormap));
+               memcpy(palette_rgb_shirtscoreboard[15], palette_rgb_shirtcolormap[15], sizeof(*palette_rgb_shirtcolormap));
+       }
+
        if (vid_hidden || !scr_refresh.integer)
                return;
 
-       if (!scr_initialized || !con_initialized)
-               return;                         // not initialized yet
+       rendertime1 = Sys_DoubleTime();
 
        conwidth = bound(320, vid_conwidth.value, 2048);
        conheight = bound(200, vid_conheight.value, 1536);
@@ -2144,9 +2178,9 @@ void CL_UpdateScreen(void)
                        sb_lines = 24+16+8;
        }
 
-       r_view.colormask[0] = 1;
-       r_view.colormask[1] = 1;
-       r_view.colormask[2] = 1;
+       r_refdef.view.colormask[0] = 1;
+       r_refdef.view.colormask[1] = 1;
+       r_refdef.view.colormask[2] = 1;
 
        SCR_SetUpToDrawConsole();
 
@@ -2158,7 +2192,9 @@ void CL_UpdateScreen(void)
        qglColorMask(1,1,1,1);CHECKGLERROR
        qglClearColor(0,0,0,0);CHECKGLERROR
        R_ClearScreen(false);
-       r_view.clear = false;
+       r_refdef.view.clear = false;
+       r_refdef.view.isoverlay = false;
+       r_refdef.view.quality = bound(cl_minfps_qualitymin.value, pow(cl_updatescreen_quality, cl_minfps_qualitypower.value) * cl_minfps_qualityscale.value, cl_minfps_qualitymax.value);
 
        if(scr_stipple.integer)
        {
@@ -2184,19 +2220,19 @@ void CL_UpdateScreen(void)
 
        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;
+               matrix4x4_t originalmatrix = r_refdef.view.matrix;
                matrix4x4_t offsetmatrix;
                Matrix4x4_CreateFromQuakeEntity(&offsetmatrix, 0, r_stereo_separation.value * 0.5f, 0, 0, r_stereo_angle.value * 0.5f, 0, 1);
-               Matrix4x4_Concat(&r_view.matrix, &originalmatrix, &offsetmatrix);
+               Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
 
                if (r_stereo_sidebyside.integer)
                        r_stereo_side = 0;
 
                if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer)
                {
-                       r_view.colormask[0] = 1;
-                       r_view.colormask[1] = 0;
-                       r_view.colormask[2] = 0;
+                       r_refdef.view.colormask[0] = 1;
+                       r_refdef.view.colormask[1] = 0;
+                       r_refdef.view.colormask[2] = 0;
                }
 
                if (vid.stereobuffer)
@@ -2205,16 +2241,16 @@ void CL_UpdateScreen(void)
                SCR_DrawScreen();
 
                Matrix4x4_CreateFromQuakeEntity(&offsetmatrix, 0, r_stereo_separation.value * -0.5f, 0, 0, r_stereo_angle.value * -0.5f, 0, 1);
-               Matrix4x4_Concat(&r_view.matrix, &originalmatrix, &offsetmatrix);
+               Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
 
                if (r_stereo_sidebyside.integer)
                        r_stereo_side = 1;
 
                if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer)
                {
-                       r_view.colormask[0] = 0;
-                       r_view.colormask[1] = r_stereo_redcyan.integer || r_stereo_redgreen.integer;
-                       r_view.colormask[2] = r_stereo_redcyan.integer || r_stereo_redblue.integer;
+                       r_refdef.view.colormask[0] = 0;
+                       r_refdef.view.colormask[1] = r_stereo_redcyan.integer || r_stereo_redgreen.integer;
+                       r_refdef.view.colormask[2] = r_stereo_redcyan.integer || r_stereo_redblue.integer;
                }
 
                if (vid.stereobuffer)
@@ -2222,14 +2258,24 @@ void CL_UpdateScreen(void)
 
                SCR_DrawScreen();
 
-               r_view.matrix = originalmatrix;
+               r_refdef.view.matrix = originalmatrix;
        }
        else
                SCR_DrawScreen();
 
        SCR_CaptureVideo();
 
-       VID_Finish(true);
+       // quality adjustment according to render time
+       qglFlush();
+       cl_updatescreen_rendertime += ((Sys_DoubleTime() - rendertime1) - cl_updatescreen_rendertime) * bound(0, cl_minfps_fade.value, 1);
+       if (cl_minfps.value > 0 && cl_updatescreen_rendertime > 0 && !cls.timedemo && (!cls.capturevideo.active || !cls.capturevideo.realtime))
+               cl_updatescreen_quality = 1 / (cl_updatescreen_rendertime * cl_minfps.value);
+       else
+               cl_updatescreen_quality = 1;
+
+       VID_GrabMouse((vid.fullscreen || (vid_mouse.integer && !key_consoleactive && (key_dest != key_game || !cls.demoplayback))) && vid_activewindow && !cl.csqc_wantsmousemove);
+
+       VID_Finish();
 }
 
 void CL_Screen_NewMap(void)