]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_backend.c
changed a lot of Con_DPrint/Con_DPrintf calls to Con_Print/Con_Printf (non-technical...
[xonotic/darkplaces.git] / gl_backend.c
index 89f2017501f664a49cfde63e26c7508296b23886..915abadef8822257f5db2748903196b4a34d76ad 100644 (file)
@@ -7,9 +7,13 @@
 cvar_t gl_mesh_drawrangeelements = {0, "gl_mesh_drawrangeelements", "1"};
 cvar_t gl_mesh_testarrayelement = {0, "gl_mesh_testarrayelement", "0"};
 cvar_t gl_mesh_testmanualfeeding = {0, "gl_mesh_testmanualfeeding", "0"};
-cvar_t gl_delayfinish = {CVAR_SAVE, "gl_delayfinish", "0"};
 cvar_t gl_paranoid = {0, "gl_paranoid", "0"};
 cvar_t gl_printcheckerror = {0, "gl_printcheckerror", "0"};
+cvar_t r_stereo_separation = {0, "r_stereo_separation", "4"};
+cvar_t r_stereo_sidebyside = {0, "r_stereo_sidebyside", "0"};
+cvar_t r_stereo_redblue = {0, "r_stereo_redblue", "0"};
+cvar_t r_stereo_redcyan = {0, "r_stereo_redcyan", "0"};
+cvar_t r_stereo_redgreen = {0, "r_stereo_redgreen", "0"};
 
 cvar_t r_render = {0, "r_render", "1"};
 cvar_t r_waterwarp = {CVAR_SAVE, "r_waterwarp", "1"};
@@ -145,7 +149,7 @@ static void R_Mesh_CacheArray_Shutdown(void);
 void GL_Backend_AllocArrays(void)
 {
        if (!gl_backend_mempool)
-               gl_backend_mempool = Mem_AllocPool("GL_Backend");
+               gl_backend_mempool = Mem_AllocPool("GL_Backend", 0, NULL);
        R_Mesh_CacheArray_Startup();
 }
 
@@ -157,7 +161,7 @@ void GL_Backend_FreeArrays(void)
 
 static void gl_backend_start(void)
 {
-       Con_DPrint("OpenGL Backend started\n");
+       Con_Print("OpenGL Backend started\n");
        if (qglDrawRangeElements != NULL)
        {
                CHECKGLERROR
@@ -165,7 +169,7 @@ static void gl_backend_start(void)
                CHECKGLERROR
                qglGetIntegerv(GL_MAX_ELEMENTS_INDICES, &gl_maxdrawrangeelementsindices);
                CHECKGLERROR
-               Con_DPrintf("glDrawRangeElements detected (max vertices %i, max indices %i)\n", gl_maxdrawrangeelementsvertices, gl_maxdrawrangeelementsindices);
+               Con_Printf("glDrawRangeElements detected (max vertices %i, max indices %i)\n", gl_maxdrawrangeelementsvertices, gl_maxdrawrangeelementsindices);
        }
 
        backendunits = min(MAX_TEXTUREUNITS, gl_textureunits);
@@ -180,7 +184,7 @@ static void gl_backend_shutdown(void)
        backendunits = 0;
        backendactive = false;
 
-       Con_DPrint("OpenGL Backend shutting down\n");
+       Con_Print("OpenGL Backend shutting down\n");
 
        GL_Backend_FreeArrays();
 }
@@ -207,10 +211,14 @@ void gl_backend_init(void)
 
        Cvar_RegisterVariable(&r_render);
        Cvar_RegisterVariable(&r_waterwarp);
+       Cvar_RegisterVariable(&r_stereo_separation);
+       Cvar_RegisterVariable(&r_stereo_sidebyside);
+       Cvar_RegisterVariable(&r_stereo_redblue);
+       Cvar_RegisterVariable(&r_stereo_redcyan);
+       Cvar_RegisterVariable(&r_stereo_redgreen);
        Cvar_RegisterVariable(&gl_polyblend);
        Cvar_RegisterVariable(&gl_dither);
        Cvar_RegisterVariable(&gl_lockarrays);
-       Cvar_RegisterVariable(&gl_delayfinish);
        Cvar_RegisterVariable(&gl_paranoid);
        Cvar_RegisterVariable(&gl_printcheckerror);
 #ifdef NORENDER
@@ -1249,7 +1257,145 @@ CalcFov
 float CalcFov (float fov_x, float width, float height)
 {
        // calculate vision size and alter by aspect, then convert back to angle
-       return atan (((height/width)/vid_pixelaspect.value)*tan(fov_x/360.*M_PI))*360./M_PI; 
+       return atan (((height/width)/vid_pixelaspect.value)*tan(fov_x/360.0*M_PI))*360.0/M_PI; 
+}
+
+int r_stereo_side;
+
+void SCR_DrawScreen (void)
+{
+       for (r_showtrispass = 0;r_showtrispass <= (r_showtris.value > 0);r_showtrispass++)
+       {
+               R_Mesh_Start();
+
+               R_TimeReport("setup");
+
+               if (r_showtrispass)
+               {
+                       rmeshstate_t m;
+                       r_showtrispass = 0;
+                       GL_BlendFunc(GL_ONE, GL_ONE);
+                       GL_DepthTest(GL_FALSE);
+                       GL_DepthMask(GL_FALSE);
+                       memset(&m, 0, sizeof(m));
+                       R_Mesh_State(&m);
+                       GL_ShowTrisColor(0.2,0.2,0.2,1);
+                       r_showtrispass = 1;
+               }
+
+               if (scr_conlines < vid.conheight && cls.signon == SIGNONS)
+               {
+                       float size;
+
+                       size = scr_viewsize.value * (1.0 / 100.0);
+                       size = min(size, 1);
+
+                       if (r_stereo_sidebyside.integer)
+                       {
+                               r_refdef.width = vid.realwidth * size / 2.5;
+                               r_refdef.height = vid.realheight * size / 2.5 * (1 - bound(0, r_letterbox.value, 100) / 100);
+                               r_refdef.x = (vid.realwidth - r_refdef.width * 2.5) * 0.5;
+                               r_refdef.y = (vid.realheight - r_refdef.height)/2;
+                               if (r_stereo_side)
+                                       r_refdef.x += r_refdef.width * 1.5;
+                       }
+                       else
+                       {
+                               r_refdef.width = vid.realwidth * size;
+                               r_refdef.height = vid.realheight * size * (1 - bound(0, r_letterbox.value, 100) / 100);
+                               r_refdef.x = (vid.realwidth - r_refdef.width)/2;
+                               r_refdef.y = (vid.realheight - r_refdef.height)/2;
+                       }
+
+                       // LordHavoc: viewzoom (zoom in for sniper rifles, etc)
+                       r_refdef.fov_x = scr_fov.value * cl.viewzoom * r_refdef.fovscale_x;
+                       r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.width, r_refdef.height) * r_refdef.fovscale_y;
+
+                       R_RenderView();
+
+                       if (scr_zoomwindow.integer)
+                       {
+                               float sizex = bound(10, scr_zoomwindow_viewsizex.value, 100) / 100.0;
+                               float sizey = bound(10, scr_zoomwindow_viewsizey.value, 100) / 100.0;
+                               r_refdef.width = vid.realwidth * sizex;
+                               r_refdef.height = vid.realheight * sizey;
+                               r_refdef.x = (vid.realwidth - r_refdef.width)/2;
+                               r_refdef.y = 0;
+                               r_refdef.fov_x = scr_zoomwindow_fov.value * r_refdef.fovscale_x;
+                               r_refdef.fov_y = CalcFov(r_refdef.fov_x, r_refdef.width, r_refdef.height) * r_refdef.fovscale_y;
+
+                               R_RenderView();
+                       }
+               }
+
+               if (!r_stereo_sidebyside.integer)
+               {
+                       r_refdef.width = vid.realwidth;
+                       r_refdef.height = vid.realheight;
+                       r_refdef.x = 0;
+                       r_refdef.y = 0;
+               }
+
+               // draw 2D stuff
+               R_DrawQueue();
+
+               R_Mesh_Finish();
+
+               R_TimeReport("meshfinish");
+       }
+       r_showtrispass = 0;
+}
+
+void SCR_UpdateLoadingScreen (void)
+{
+       float x, y;
+       cachepic_t *pic;
+       rmeshstate_t m;
+       // don't do anything if not initialized yet
+       if (vid_hidden)
+               return;
+       r_showtrispass = 0;
+       VID_GetWindowSize(&vid.realx, &vid.realy, &vid.realwidth, &vid.realheight);
+       VID_UpdateGamma(false);
+       qglViewport(0, 0, vid.realwidth, vid.realheight);
+       //qglDisable(GL_SCISSOR_TEST);
+       //qglDepthMask(1);
+       qglColorMask(1,1,1,1);
+       //qglClearColor(0,0,0,0);
+       //qglClear(GL_COLOR_BUFFER_BIT);
+       //qglCullFace(GL_FRONT);
+       //qglDisable(GL_CULL_FACE);
+       //R_ClearScreen();
+       R_Textures_Frame();
+       GL_SetupView_Mode_Ortho(0, 0, vid_conwidth.integer, vid_conheight.integer, -10, 100);
+       R_Mesh_Start();
+       R_Mesh_Matrix(&r_identitymatrix);
+       // draw the loading plaque
+       pic = Draw_CachePic("gfx/loading.lmp");
+       x = (vid_conwidth.integer - pic->width)/2;
+       y = (vid_conheight.integer - pic->height)/2;
+       GL_Color(1,1,1,1);
+       GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+       GL_DepthTest(false);
+       memset(&m, 0, sizeof(m));
+       m.pointer_vertex = varray_vertex3f;
+       m.pointer_texcoord[0] = varray_texcoord2f[0];
+       m.tex[0] = R_GetTexture(pic->tex);
+       R_Mesh_State(&m);
+       varray_vertex3f[0] = varray_vertex3f[9] = x;
+       varray_vertex3f[1] = varray_vertex3f[4] = y;
+       varray_vertex3f[3] = varray_vertex3f[6] = x + pic->width;
+       varray_vertex3f[7] = varray_vertex3f[10] = y + pic->height;
+       varray_texcoord2f[0][0] = 0;varray_texcoord2f[0][1] = 0;
+       varray_texcoord2f[0][2] = 1;varray_texcoord2f[0][3] = 0;
+       varray_texcoord2f[0][4] = 1;varray_texcoord2f[0][5] = 1;
+       varray_texcoord2f[0][6] = 0;varray_texcoord2f[0][7] = 1;
+       GL_LockArrays(0, 4);
+       R_Mesh_Draw(4, 2, polygonelements);
+       GL_LockArrays(0, 0);
+       R_Mesh_Finish();
+       // refresh
+       VID_Finish();
 }
 
 /*
@@ -1262,15 +1408,8 @@ text to the screen.
 */
 void SCR_UpdateScreen (void)
 {
-       if (gl_delayfinish.integer)
-       {
-               R_Mesh_Finish();
-               R_TimeReport("meshfinish");
-               VID_Finish();
-               R_TimeReport("finish");
-       }
-
-       R_Mesh_Start();
+       if (vid_hidden)
+               return;
 
        if (r_textureunits.integer > gl_textureunits)
                Cvar_SetValueQuick(&r_textureunits, gl_textureunits);
@@ -1280,120 +1419,126 @@ void SCR_UpdateScreen (void)
        if (gl_combine.integer && (!gl_combine_extension || r_textureunits.integer < 2))
                Cvar_SetValueQuick(&gl_combine, 0);
 
-showtris:
-       R_TimeReport("setup");
-
-       R_ClearScreen();
-
-       R_TimeReport("clear");
+       // don't allow cheats in multiplayer
+       if (!cl.islocalgame && cl.worldmodel)
+       {
+               if (r_fullbright.integer != 0)
+                       Cvar_Set ("r_fullbright", "0");
+               if (r_ambient.value != 0)
+                       Cvar_Set ("r_ambient", "0");
+       }
 
-       if (scr_conlines < vid.conheight && cls.signon == SIGNONS)
+       // bound viewsize
+       if (scr_viewsize.value < 30)
+               Cvar_Set ("viewsize","30");
+       if (scr_viewsize.value > 120)
+               Cvar_Set ("viewsize","120");
+
+       // bound field of view
+       if (scr_fov.value < 1)
+               Cvar_Set ("fov","1");
+       if (scr_fov.value > 170)
+               Cvar_Set ("fov","170");
+
+       // intermission is always full screen
+       if (cl.intermission)
+               sb_lines = 0;
+       else
        {
-               float size;
-               int contents;
-
-               // bound viewsize
-               if (scr_viewsize.value < 30)
-                       Cvar_Set ("viewsize","30");
-               if (scr_viewsize.value > 120)
-                       Cvar_Set ("viewsize","120");
-               
-               // bound field of view
-               if (scr_fov.value < 1)
-                       Cvar_Set ("fov","1");
-               if (scr_fov.value > 170)
-                       Cvar_Set ("fov","170");
-       
-               // intermission is always full screen
-               if (cl.intermission)
-               {
-                       size = 1;
-                       sb_lines = 0;
-               }
+               if (scr_viewsize.value >= 120)
+                       sb_lines = 0;           // no status bar at all
+               else if (scr_viewsize.value >= 110)
+                       sb_lines = 24;          // no inventory
                else
+                       sb_lines = 24+16+8;
+       }
+
+       r_refdef.fovscale_x = 1;
+       r_refdef.fovscale_y = 1;
+       if (r_waterwarp.value > 0 && cl.worldmodel)
+       {
+               Mod_CheckLoaded(cl.worldmodel);
+               if (CL_PointSuperContents(r_vieworigin) & SUPERCONTENTS_LIQUIDSMASK)
                {
-                       if (scr_viewsize.value >= 120)
-                               sb_lines = 0;           // no status bar at all
-                       else if (scr_viewsize.value >= 110)
-                               sb_lines = 24;          // no inventory
-                       else
-                               sb_lines = 24+16+8;
-                       size = scr_viewsize.value * (1.0 / 100.0);
-                       size = min(size, 1);
+                       r_refdef.fovscale_x = 1 - (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value);
+                       r_refdef.fovscale_y = 1 - (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value);
                }
-       
-               r_refdef.width = vid.realwidth * size;
-               r_refdef.height = vid.realheight * size;
-               r_refdef.x = (vid.realwidth - r_refdef.width)/2;
-               r_refdef.y = (vid.realheight - r_refdef.height)/2;
-       
-               // LordHavoc: viewzoom (zoom in for sniper rifles, etc)
-               r_refdef.fov_x = scr_fov.value * cl.viewzoom;
-               r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.width, r_refdef.height);
+       }
+
+       r_refdef.colormask[0] = 1;
+       r_refdef.colormask[1] = 1;
+       r_refdef.colormask[2] = 1;
+
+       CHECKGLERROR
+       qglViewport(0, 0, vid.realwidth, vid.realheight);
+       qglDisable(GL_SCISSOR_TEST);
+       qglDepthMask(1);
+       qglColorMask(1,1,1,1);
+       qglClearColor(0,0,0,0);
+       qglClear(GL_COLOR_BUFFER_BIT);
+       CHECKGLERROR
+
+       R_TimeReport("clear");
+
+       if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer || r_stereo_sidebyside.integer)
+       {
+               matrix4x4_t originalmatrix = r_refdef.viewentitymatrix;
+               r_refdef.viewentitymatrix.m[0][3] = originalmatrix.m[0][3] + r_stereo_separation.value * -0.5f * r_refdef.viewentitymatrix.m[0][1];
+               r_refdef.viewentitymatrix.m[1][3] = originalmatrix.m[1][3] + r_stereo_separation.value * -0.5f * r_refdef.viewentitymatrix.m[1][1];
+               r_refdef.viewentitymatrix.m[2][3] = originalmatrix.m[2][3] + r_stereo_separation.value * -0.5f * r_refdef.viewentitymatrix.m[2][1];
+
+               if (r_stereo_sidebyside.integer)
+                       r_stereo_side = 0;
 
-               if (r_waterwarp.value > 0)
+               if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer)
                {
-                       if (cl.worldmodel)
-                       {
-                               Mod_CheckLoaded(cl.worldmodel);
-                               contents = CL_PointSuperContents(r_vieworigin);
-                               if (contents & SUPERCONTENTS_LIQUIDSMASK)
-                               {
-                                       r_refdef.fov_x *= 1 - (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value);
-                                       r_refdef.fov_y *= 1 - (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value);
-                               }
-                       }
+                       r_refdef.colormask[0] = 1;
+                       r_refdef.colormask[1] = 0;
+                       r_refdef.colormask[2] = 0;
                }
 
-               R_RenderView();
+               SCR_DrawScreen();
 
-               if (scr_zoomwindow.integer)
-               {
-                       float sizex = bound(10, scr_zoomwindow_viewsizex.value, 100) / 100.0;
-                       float sizey = bound(10, scr_zoomwindow_viewsizey.value, 100) / 100.0;
-                       r_refdef.width = vid.realwidth * sizex;
-                       r_refdef.height = vid.realheight * sizey;
-                       r_refdef.x = (vid.realwidth - r_refdef.width)/2;
-                       r_refdef.y = 0;
-                       r_refdef.fov_x = scr_zoomwindow_fov.value;
-                       r_refdef.fov_y = CalcFov(r_refdef.fov_x, r_refdef.width, r_refdef.height);
+               r_refdef.viewentitymatrix.m[0][3] = originalmatrix.m[0][3] + r_stereo_separation.value * 0.5f * r_refdef.viewentitymatrix.m[0][1];
+               r_refdef.viewentitymatrix.m[1][3] = originalmatrix.m[1][3] + r_stereo_separation.value * 0.5f * r_refdef.viewentitymatrix.m[1][1];
+               r_refdef.viewentitymatrix.m[2][3] = originalmatrix.m[2][3] + r_stereo_separation.value * 0.5f * r_refdef.viewentitymatrix.m[2][1];
 
-                       R_RenderView();
+               if (r_stereo_sidebyside.integer)
+                       r_stereo_side = 1;
+
+               if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer)
+               {
+                       r_refdef.colormask[0] = 0;
+                       r_refdef.colormask[1] = r_stereo_redcyan.integer || r_stereo_redgreen.integer;
+                       r_refdef.colormask[2] = r_stereo_redcyan.integer || r_stereo_redblue.integer;
                }
-       }
 
-       // draw 2D stuff
-       R_DrawQueue();
+               SCR_DrawScreen();
 
-       if (r_showtrispass)
-               r_showtrispass = false;
-       else if (r_showtris.value > 0)
-       {
-               rmeshstate_t m;
-               GL_BlendFunc(GL_ONE, GL_ONE);
-               GL_DepthTest(GL_FALSE);
-               GL_DepthMask(GL_FALSE);
-               memset(&m, 0, sizeof(m));
-               R_Mesh_State(&m);
-               r_showtrispass = true;
-               GL_ShowTrisColor(0.2,0.2,0.2,1);
-               goto showtris;
-       }
-
-       if (gl_delayfinish.integer)
-       {
-               // tell driver to commit it's partially full geometry queue to the rendering queue
-               // (this doesn't wait for the commands themselves to complete)
-               if (gl_finish.integer)
-                       qglFlush();
+               r_refdef.viewentitymatrix = originalmatrix;
        }
        else
        {
-               R_Mesh_Finish();
-               R_TimeReport("meshfinish");
-               VID_Finish();
-               R_TimeReport("finish");
+               r_showtrispass = false;
+               SCR_DrawScreen();
+       
+               if (r_showtris.value > 0)
+               {
+                       rmeshstate_t m;
+                       GL_BlendFunc(GL_ONE, GL_ONE);
+                       GL_DepthTest(GL_FALSE);
+                       GL_DepthMask(GL_FALSE);
+                       memset(&m, 0, sizeof(m));
+                       R_Mesh_State(&m);
+                       r_showtrispass = true;
+                       GL_ShowTrisColor(0.2,0.2,0.2,1);
+                       SCR_DrawScreen();
+                       r_showtrispass = false;
+               }
        }
+
+       VID_Finish();
+       R_TimeReport("finish");
 }
 
 
@@ -1401,12 +1546,16 @@ showtris:
 // dynamic vertex array buffer subsystem
 //===========================================================================
 
+// FIXME: someday this should be dynamically allocated and resized?
 float varray_vertex3f[65536*3];
+float varray_svector3f[65536*3];
+float varray_tvector3f[65536*3];
+float varray_normal3f[65536*3];
 float varray_color4f[65536*4];
 float varray_texcoord2f[4][65536*2];
 float varray_texcoord3f[4][65536*3];
-float varray_normal3f[65536*3];
 int earray_element3i[65536];
+float varray_vertex3f2[65536*3];
 
 //===========================================================================
 // vertex array caching subsystem