]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_screen.c
new r_stereo modes (horiz and vert split)
[xonotic/darkplaces.git] / cl_screen.c
index 895f5164265d66f744d2ae9228964032d99ffb8f..84f23b35fae3cc9477885608015de67b43c40328 100644 (file)
@@ -18,7 +18,7 @@ cvar_t scr_fov = {CVAR_SAVE, "fov","90", "field of vision, 1-170 degrees, defaul
 cvar_t scr_conalpha = {CVAR_SAVE, "scr_conalpha", "1", "opacity of console background gfx/conback"};
 cvar_t scr_conalphafactor = {CVAR_SAVE, "scr_conalphafactor", "1", "opacity of console background gfx/conback relative to scr_conalpha; when 0, gfx/conback is not drawn"};
 cvar_t scr_conalpha2factor = {CVAR_SAVE, "scr_conalpha2factor", "0", "opacity of console background gfx/conback2 relative to scr_conalpha; when 0, gfx/conback2 is not drawn"};
-cvar_t scr_conalpha3factor = {CVAR_SAVE, "scr_conalpha3factor", "0", "opacity of console background gfx/conback3 relative to scr_conalpha; when 0, gfx/conback is not drawn"};
+cvar_t scr_conalpha3factor = {CVAR_SAVE, "scr_conalpha3factor", "0", "opacity of console background gfx/conback3 relative to scr_conalpha; when 0, gfx/conback3 is not drawn"};
 cvar_t scr_conbrightness = {CVAR_SAVE, "scr_conbrightness", "1", "brightness of console background (0 = black, 1 = image)"};
 cvar_t scr_conforcewhiledisconnected = {0, "scr_conforcewhiledisconnected", "1", "forces fullscreen console while disconnected"};
 cvar_t scr_conscroll_x = {CVAR_SAVE, "scr_conscroll_x", "0", "scroll speed of gfx/conback in x direction"};
@@ -61,6 +61,8 @@ cvar_t cl_capturevideo_framestep = {CVAR_SAVE, "cl_capturevideo_framestep", "1",
 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)"};
+cvar_t r_stereo_horizontal = {0, "r_stereo_horizontal", "0", "aspect skewed side by side view for special decoder/display hardware"};
+cvar_t r_stereo_vertical = {0, "r_stereo_vertical", "0", "aspect skewed top and bottom view for special decoder/display hardware"};
 cvar_t r_stereo_redblue = {0, "r_stereo_redblue", "0", "red/blue anaglyph stereo glasses (note: most of these glasses are actually red/cyan, try that one too)"};
 cvar_t r_stereo_redcyan = {0, "r_stereo_redcyan", "0", "red/cyan anaglyph stereo glasses, the kind given away at drive-in movies like Creature From The Black Lagoon In 3D"};
 cvar_t r_stereo_redgreen = {0, "r_stereo_redgreen", "0", "red/green anaglyph stereo glasses (for those who don't mind yellow)"};
@@ -696,7 +698,7 @@ int speedstringcount, r_timereport_active;
 double r_timereport_temp = 0, r_timereport_current = 0, r_timereport_start = 0;
 int r_speeds_longestitem = 0;
 
-void R_TimeReport(char *desc)
+void R_TimeReport(const char *desc)
 {
        char tempbuf[256];
        int length;
@@ -706,7 +708,7 @@ void R_TimeReport(char *desc)
                return;
 
        CHECKGLERROR
-       if (r_speeds.integer == 2)
+       if (r_speeds.integer == 2 && qglFinish)
                qglFinish();
        CHECKGLERROR
        r_timereport_temp = r_timereport_current;
@@ -909,6 +911,8 @@ void CL_Screen_Init(void)
        Cvar_RegisterVariable (&r_letterbox);
        Cvar_RegisterVariable(&r_stereo_separation);
        Cvar_RegisterVariable(&r_stereo_sidebyside);
+       Cvar_RegisterVariable(&r_stereo_horizontal);
+       Cvar_RegisterVariable(&r_stereo_vertical);
        Cvar_RegisterVariable(&r_stereo_redblue);
        Cvar_RegisterVariable(&r_stereo_redcyan);
        Cvar_RegisterVariable(&r_stereo_redgreen);
@@ -1006,14 +1010,14 @@ void SCR_ScreenShot_f (void)
        buffer1 = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * 4);
        buffer2 = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * (scr_screenshot_alpha.integer ? 4 : 3));
 
-       if (SCR_ScreenShot (filename, buffer1, buffer2, 0, 0, vid.width, vid.height, false, false, false, jpeg, png, true, scr_screenshot_alpha.integer))
+       if (SCR_ScreenShot (filename, buffer1, buffer2, 0, 0, vid.width, vid.height, false, false, false, jpeg, png, true, scr_screenshot_alpha.integer != 0))
                Con_Printf("Wrote %s\n", filename);
        else
        {
                Con_Printf("Unable to write %s\n", filename);
                if(jpeg || png)
                {
-                       if(SCR_ScreenShot (filename, buffer1, buffer2, 0, 0, vid.width, vid.height, false, false, false, false, false, true, scr_screenshot_alpha.integer))
+                       if(SCR_ScreenShot (filename, buffer1, buffer2, 0, 0, vid.width, vid.height, false, false, false, false, false, true, scr_screenshot_alpha.integer != 0))
                        {
                                strlcpy(filename + strlen(filename) - 3, "tga", 4);
                                Con_Printf("Wrote %s\n", filename);
@@ -1231,7 +1235,8 @@ void SCR_CaptureVideo_VideoFrame(int newframestepframenum)
        CHECKGLERROR
        // speed is critical here, so do saving as directly as possible
 
-       qglReadPixels (x, y, vid.width, vid.height, GL_BGRA, GL_UNSIGNED_BYTE, cls.capturevideo.screenbuffer);CHECKGLERROR
+       GL_ReadPixelsBGRA(x, y, vid.width, vid.height, cls.capturevideo.screenbuffer);
+
        SCR_ScaleDownBGRA (cls.capturevideo.screenbuffer, vid.width, vid.height, cls.capturevideo.outbuffer, width, height);
 
        cls.capturevideo.videoframes(newframestepframenum - cls.capturevideo.framestepframe);
@@ -1313,7 +1318,7 @@ Grab six views for environment mapping tests
 struct envmapinfo_s
 {
        float angles[3];
-       char *name;
+       const char *name;
        qboolean flipx, flipy, flipdiagonaly;
 }
 envmapinfo[12] =
@@ -1458,7 +1463,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), 0, 0, 1, 1, 1, 1, 0);
+                       DrawQ_Pic(cl.showlmps[i].x, cl.showlmps[i].y, Draw_CachePic_Flags (cl.showlmps[i].pic, CACHEPICFLAG_NOTPERSISTENT), 0, 0, 1, 1, 1, 1, 0);
 }
 
 /*
@@ -1476,8 +1481,7 @@ qboolean SCR_ScreenShot(char *filename, unsigned char *buffer1, unsigned char *b
        int     indices[4] = {0,1,2,3}; // BGRA
        qboolean ret;
 
-       CHECKGLERROR
-       qglReadPixels (x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, buffer1);CHECKGLERROR
+       GL_ReadPixelsBGRA(x, y, width, height, buffer1);
 
        if(gammacorrect && (scr_screenshot_gammaboost.value != 1 || WANT_SCREENSHOT_HWGAMMA))
        {
@@ -1543,36 +1547,20 @@ qboolean SCR_ScreenShot(char *filename, unsigned char *buffer1, unsigned char *b
 extern void R_UpdateFogColor(void);
 void R_ClearScreen(qboolean fogcolor)
 {
+       float clearcolor[4];
        // clear to black
-       CHECKGLERROR
+       Vector4Clear(clearcolor);
        if (fogcolor)
        {
                R_UpdateFogColor();
-               qglClearColor(r_refdef.fogcolor[0],r_refdef.fogcolor[1],r_refdef.fogcolor[2],0);CHECKGLERROR
-       }
-       else
-       {
-               qglClearColor(0,0,0,0);CHECKGLERROR
-       }
-       qglClearDepth(1);CHECKGLERROR
-       if (vid.stencil)
-       {
-               // LordHavoc: we use a stencil centered around 128 instead of 0,
-               // to avoid clamping interfering with strange shadow volume
-               // drawing orders
-               qglClearStencil(128);CHECKGLERROR
+               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));
-       // set dithering mode
-       if (gl_dither.integer)
-       {
-               qglEnable(GL_DITHER);CHECKGLERROR
-       }
-       else
-       {
-               qglDisable(GL_DITHER);CHECKGLERROR
-       }
+       GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | (vid.stencil ? GL_STENCIL_BUFFER_BIT : 0), clearcolor, 1.0f, 128);
 }
 
 qboolean CL_VM_UpdateView (void);
@@ -1612,6 +1600,28 @@ void SCR_DrawScreen (void)
                        if (r_stereo_side)
                                r_refdef.view.x += (int)(r_refdef.view.width * 1.5);
                }
+               else if (r_stereo_horizontal.integer)
+               {
+                       r_refdef.view.width = (int)(vid.width * size / 2);
+                       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.0)/2);
+                       r_refdef.view.y = (int)((vid.height - r_refdef.view.height)/2);
+                       r_refdef.view.z = 0;
+                       if (r_stereo_side)
+                               r_refdef.view.x += (int)(r_refdef.view.width);
+               }
+               else if (r_stereo_vertical.integer)
+               {
+                       r_refdef.view.width = (int)(vid.width * size);
+                       r_refdef.view.height = (int)(vid.height * size * (1 - bound(0, r_letterbox.value, 100) / 100) / 2);
+                       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.0)/2);
+                       r_refdef.view.z = 0;
+                       if (r_stereo_side)
+                               r_refdef.view.y += (int)(r_refdef.view.height);
+               }
                else
                {
                        r_refdef.view.width = (int)(vid.width * size);
@@ -1661,7 +1671,7 @@ void SCR_DrawScreen (void)
                }
        }
 
-       if (!r_stereo_sidebyside.integer)
+       if (!r_stereo_sidebyside.integer && !r_stereo_horizontal.integer && !r_stereo_vertical.integer)
        {
                r_refdef.view.width = vid.width;
                r_refdef.view.height = vid.height;
@@ -1793,7 +1803,7 @@ static void SCR_SetLoadingScreenTexture(void)
                loadingscreentexture_h = vid.height / (float) h;
        }
 
-       loadingscreentexture = R_LoadTexture2D(r_main_texturepool, "loadingscreentexture", w, h, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
+       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);
 
        loadingscreentexture_vertex3f[2] = loadingscreentexture_vertex3f[5] = loadingscreentexture_vertex3f[8] = loadingscreentexture_vertex3f[11] = 0;
@@ -1952,16 +1962,14 @@ static void SCR_DrawLoadingScreen_SharedSetup (qboolean clear)
        // release mouse grab while loading
        if (!vid.fullscreen)
                VID_SetMouse(false, false, false);
-       CHECKGLERROR
+//     CHECKGLERROR
+       r_refdef.draw2dstage = true;
        R_Viewport_InitOrtho(&viewport, &identitymatrix, 0, 0, vid.width, vid.height, 0, 0, vid_conwidth.integer, vid_conheight.integer, -10, 100, NULL);
        R_SetViewport(&viewport);
-       //qglDisable(GL_SCISSOR_TEST);CHECKGLERROR
-       //qglDepthMask(1);CHECKGLERROR
-       qglColorMask(1,1,1,1);CHECKGLERROR
-       qglClearColor(0,0,0,0);CHECKGLERROR
+       GL_ColorMask(1,1,1,1);
        // when starting up a new video mode, make sure the screen is cleared to black
        if (clear)
-               qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
+               GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 0);
        R_Textures_Frame();
        R_Mesh_Start();
        R_EntityMatrix(&identitymatrix);
@@ -2006,8 +2014,6 @@ static void SCR_DrawLoadingScreen_SharedFinish (qboolean clear)
        R_Mesh_Finish();
        // refresh
        VID_Finish();
-       // however this IS necessary on Windows Vista
-       qglFinish();
 }
 
 void SCR_UpdateLoadingScreen (qboolean clear)
@@ -2050,7 +2056,8 @@ void SCR_UpdateLoadingScreen (qboolean clear)
        }
        else
        {
-               qglDrawBuffer(GL_BACK);
+               if (qglDrawBuffer)
+                       qglDrawBuffer(GL_BACK);
                SCR_DrawLoadingScreen(clear);
        }
        SCR_DrawLoadingScreen_SharedFinish(clear);
@@ -2072,7 +2079,7 @@ qboolean R_Stereo_ColorMasking(void)
 
 qboolean R_Stereo_Active(void)
 {
-       return (vid.stereobuffer || r_stereo_sidebyside.integer || R_Stereo_ColorMasking());
+       return (vid.stereobuffer || r_stereo_sidebyside.integer || r_stereo_horizontal.integer || r_stereo_vertical.integer || R_Stereo_ColorMasking());
 }
 
 extern cvar_t cl_minfps;
@@ -2089,13 +2096,14 @@ void CL_UpdateScreen(void)
        double rendertime1;
        float conwidth, conheight;
        float f;
+       r_viewport_t viewport;
 
        Sbar_ShowFPS_Update();
 
        if (!scr_initialized || !con_initialized || !scr_refresh.integer)
                return;                         // not initialized yet
 
-       if(gamemode == GAME_NEXUIZ)
+       if(gamemode == GAME_NEXUIZ || gamemode == GAME_XONOTIC)
        {
                // 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));
@@ -2109,7 +2117,10 @@ void CL_UpdateScreen(void)
        }
 
        if (vid_hidden)
+       {
+               VID_Finish();
                return;
+       }
 
        rendertime1 = Sys_DoubleTime();
 
@@ -2151,13 +2162,27 @@ void CL_UpdateScreen(void)
 
        SCR_SetUpToDrawConsole();
 
-       CHECKGLERROR
-       qglDrawBuffer(GL_BACK);CHECKGLERROR
-       qglViewport(0, 0, vid.width, vid.height);CHECKGLERROR
-       qglDisable(GL_SCISSOR_TEST);CHECKGLERROR
-       qglDepthMask(1);CHECKGLERROR
-       qglColorMask(1,1,1,1);CHECKGLERROR
-       qglClearColor(0,0,0,0);CHECKGLERROR
+       if (qglDrawBuffer)
+       {
+               CHECKGLERROR
+               qglDrawBuffer(GL_BACK);CHECKGLERROR
+               // set dithering mode
+               if (gl_dither.integer)
+               {
+                       qglEnable(GL_DITHER);CHECKGLERROR
+               }
+               else
+               {
+                       qglDisable(GL_DITHER);CHECKGLERROR
+               }
+       }
+
+       R_Viewport_InitOrtho(&viewport, &identitymatrix, 0, 0, vid.width, vid.height, 0, 0, vid_conwidth.integer, vid_conheight.integer, -10, 100, NULL);
+       R_SetViewport(&viewport);
+       GL_ScissorTest(false);
+       GL_ColorMask(1,1,1,1);
+       GL_DepthMask(true);
+
        R_ClearScreen(false);
        r_refdef.view.clear = false;
        r_refdef.view.isoverlay = false;
@@ -2191,7 +2216,6 @@ void CL_UpdateScreen(void)
                }
        }
 
-       CHECKGLERROR
        if (R_Stereo_Active())
        {
                matrix4x4_t originalmatrix = r_refdef.view.matrix;
@@ -2199,8 +2223,7 @@ void CL_UpdateScreen(void)
                Matrix4x4_CreateFromQuakeEntity(&offsetmatrix, 0, r_stereo_separation.value * 0.5f, 0, 0, r_stereo_angle.value * 0.5f, 0, 1);
                Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
 
-               if (r_stereo_sidebyside.integer)
-                       r_stereo_side = 0;
+               r_stereo_side = 0;
 
                if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer)
                {
@@ -2217,8 +2240,7 @@ void CL_UpdateScreen(void)
                Matrix4x4_CreateFromQuakeEntity(&offsetmatrix, 0, r_stereo_separation.value * -0.5f, 0, 0, r_stereo_angle.value * -0.5f, 0, 1);
                Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
 
-               if (r_stereo_sidebyside.integer)
-                       r_stereo_side = 1;
+               r_stereo_side = 1;
 
                if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer)
                {
@@ -2236,13 +2258,13 @@ void CL_UpdateScreen(void)
        }
        else
                SCR_DrawScreen();
-       CHECKGLERROR
 
        SCR_CaptureVideo();
 
+       if (qglFlush)
+               qglFlush(); // FIXME: should we really be using qglFlush here?
+
        // quality adjustment according to render time
-       CHECKGLERROR
-       qglFlush(); // FIXME: should we really be using qglFlush here?
        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);
@@ -2258,7 +2280,7 @@ void CL_UpdateScreen(void)
        else if (key_dest == key_menu)
                VID_SetMouse(vid.fullscreen, vid_mouse.integer && !in_client_mouse, true);
        else
-               VID_SetMouse(vid.fullscreen, vid_mouse.integer && !cl.csqc_wantsmousemove && (!cls.demoplayback || cl_demo_mousegrab.integer), true);
+               VID_SetMouse(vid.fullscreen, vid_mouse.integer && !cl.csqc_wantsmousemove && cl_prydoncursor.integer <= 0 && (!cls.demoplayback || cl_demo_mousegrab.integer), true);
 
        VID_Finish();
 }