]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_backend.c
a rather hefty 6% speed gain by getting rid of the R_Mesh_UpdateFarClip function...
[xonotic/darkplaces.git] / gl_backend.c
index 4c1cd30d7722ed41281e7ee53ed31144d6c045d1..0cc530dcae3c30c1aea3bd26d168ccbe7ab7c3d3 100644 (file)
@@ -4,7 +4,7 @@
 cvar_t gl_mesh_maxtriangles = {0, "gl_mesh_maxtriangles", "1024"};
 cvar_t gl_mesh_batchtriangles = {0, "gl_mesh_batchtriangles", "0"};
 cvar_t gl_mesh_transtriangles = {0, "gl_mesh_transtriangles", "16384"};
-cvar_t gl_mesh_floatcolors = {0, "gl_mesh_floatcolors", "0"};
+cvar_t gl_mesh_floatcolors = {0, "gl_mesh_floatcolors", "1"};
 cvar_t gl_mesh_drawmode = {CVAR_SAVE, "gl_mesh_drawmode", "3"};
 
 cvar_t r_render = {0, "r_render", "1"};
@@ -69,17 +69,19 @@ void GL_PrintError(int errornumber, char *filename, int linenumber)
 }
 #endif
 
-float r_farclip, r_newfarclip;
+float r_mesh_farclip;
 
 int polyindexarray[768];
 
 static float viewdist;
+// sign bits (true if negative) for vpn[] entries, so quick integer compares can be used instead of float compares
+static int vpnbit0, vpnbit1, vpnbit2;
 
 int c_meshs, c_meshtris, c_transmeshs, c_transtris;
 
-int                    lightscalebit;
-float          lightscale;
-float          overbrightscale;
+int lightscalebit;
+float lightscale;
+float overbrightscale;
 
 void SCR_ScreenShot_f (void);
 
@@ -145,7 +147,6 @@ typedef struct
 }
 buf_texcoord_t;
 
-static float meshfarclip;
 static int currentmesh, currenttriangle, currentvertex, backendunits, backendactive, transranout;
 static buf_mesh_t *buf_mesh;
 static buf_tri_t *buf_tri;
@@ -173,9 +174,14 @@ static void gl_backend_start(void)
        qglGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &gl_maxdrawrangeelementsvertices);
        qglGetIntegerv(GL_MAX_ELEMENTS_INDICES, &gl_maxdrawrangeelementsindices);
 
-       Con_Printf("OpenGL Backend started with gl_mesh_maxtriangles %i, gl_mesh_transtriangles %i", gl_mesh_maxtriangles.integer, gl_mesh_transtriangles.integer);
+       Con_Printf("OpenGL Backend started with gl_mesh_maxtriangles %i, gl_mesh_transtriangles %i\n", gl_mesh_maxtriangles.integer, gl_mesh_transtriangles.integer);
        if (qglDrawRangeElements != NULL)
-               Con_Printf(", with glDrawRangeElements (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);
+       if (strstr(gl_renderer, "3Dfx"))
+       {
+               Con_Printf("3Dfx driver detected, forcing gl_mesh_floatcolors to 0 to prevent crashs\n");
+               Cvar_SetValueQuick(&gl_mesh_floatcolors, 0);
+       }
        Con_Printf("\n");
 
        max_verts = max_meshs * 3;
@@ -268,8 +274,8 @@ static void gl_backend_bufferchanges(int init)
        if (gl_mesh_transtriangles.integer > 65536)
                Cvar_SetValueQuick(&gl_mesh_transtriangles, 65536);
 
-       if (gl_mesh_batchtriangles.integer < 0)
-               Cvar_SetValueQuick(&gl_mesh_batchtriangles, 0);
+       if (gl_mesh_batchtriangles.integer < 1)
+               Cvar_SetValueQuick(&gl_mesh_batchtriangles, 1);
        if (gl_mesh_batchtriangles.integer > gl_mesh_maxtriangles.integer)
                Cvar_SetValueQuick(&gl_mesh_batchtriangles, gl_mesh_maxtriangles.integer);
 
@@ -292,7 +298,6 @@ static void gl_backend_bufferchanges(int init)
 
 static void gl_backend_newmap(void)
 {
-       r_farclip = r_newfarclip = 2048.0f;
 }
 
 void gl_backend_init(void)
@@ -353,9 +358,6 @@ static void GL_SetupFrame (void)
        double xmax, ymax;
        double fovx, fovy, zNear, zFar, aspect;
 
-       // update farclip based on previous frame
-       r_farclip = r_newfarclip;
-
        if (!r_render.integer)
                return;
 
@@ -370,7 +372,7 @@ static void GL_SetupFrame (void)
 
        // depth range
        zNear = 1.0;
-       zFar = r_farclip;
+       zFar = r_mesh_farclip;
 
        // fov angles
        fovx = r_refdef.fov_x;
@@ -493,7 +495,7 @@ void GL_SetupTextureState(void)
 
 // called at beginning of frame
 int usedarrays;
-void R_Mesh_Start(void)
+void R_Mesh_Start(float farclip)
 {
        int i;
        if (!backendactive)
@@ -509,9 +511,12 @@ void R_Mesh_Start(void)
        currenttransmesh = 0;
        currenttranstriangle = 0;
        currenttransvertex = 0;
-       meshfarclip = 0;
        transranout = false;
+       r_mesh_farclip = farclip;
        viewdist = DotProduct(r_origin, vpn);
+       vpnbit0 = vpn[0] < 0;
+       vpnbit1 = vpn[1] < 0;
+       vpnbit2 = vpn[2] < 0;
 
        c_meshs = 0;
        c_meshtris = 0;
@@ -567,27 +572,6 @@ void R_Mesh_Start(void)
 
 int gl_backend_rebindtextures;
 
-void GL_UpdateFarclip(void)
-{
-       int i;
-       float farclip;
-
-       // push out farclip based on vertices
-       // FIXME: wouldn't this be slow when using matrix transforms?
-       for (i = 0;i < currentvertex;i++)
-       {
-               farclip = DotProduct(buf_vertex[i].v, vpn);
-               if (meshfarclip < farclip)
-                       meshfarclip = farclip;
-       }
-
-       farclip = meshfarclip + 256.0f - viewdist; // + 256 just to be safe
-
-       // push out farclip for next frame
-       if (farclip > r_newfarclip)
-               r_newfarclip = ceil((farclip + 255) / 256) * 256 + 256;
-}
-
 void GL_ConvertColorsFloatToByte(void)
 {
        int i, k, total;
@@ -816,8 +800,6 @@ void R_Mesh_Render(void)
 
        CHECKGLERROR
 
-       GL_UpdateFarclip();
-
        // drawmode 0 always uses byte colors
        if (!gl_mesh_floatcolors.integer || gl_mesh_drawmode.integer <= 0)
                GL_ConvertColorsFloatToByte();
@@ -863,7 +845,8 @@ void R_Mesh_Finish(void)
 {
        int i;
        // flush any queued meshs
-       R_Mesh_Render();
+       if (currentmesh)
+               R_Mesh_Render();
 
        if (backendunits > 1)
        {
@@ -915,10 +898,13 @@ void R_Mesh_Finish(void)
 
 void R_Mesh_ClearDepth(void)
 {
-       R_Mesh_AddTransparent();
+       if (currenttransmesh)
+               R_Mesh_AddTransparent();
+       if (currentmesh)
+               R_Mesh_Render();
        R_Mesh_Finish();
        qglClear(GL_DEPTH_BUFFER_BIT);
-       R_Mesh_Start();
+       R_Mesh_Start(r_mesh_farclip);
 }
 
 void R_Mesh_AddTransparent(void)
@@ -949,7 +935,7 @@ void R_Mesh_AddTransparent(void)
        }
 
        // map farclip to 0-4095 list range
-       centerscaler = (TRANSDEPTHRES / r_farclip) * (1.0f / 3.0f);
+       centerscaler = (TRANSDEPTHRES / r_mesh_farclip) * (1.0f / 3.0f);
        viewdistcompare = viewdist + 4.0f;
 
        memset(buf_sorttranstri_list, 0, TRANSDEPTHRES * sizeof(buf_transtri_t *));
@@ -1165,12 +1151,13 @@ void R_Mesh_Draw(const rmeshinfo_t *m)
 
        overbright = false;
        scaler = 1;
-       if (m->blendfunc2 == GL_SRC_COLOR)
+       if (m->blendfunc1 == GL_DST_COLOR)
        {
-               if (m->blendfunc1 == GL_DST_COLOR) // 2x modulate with framebuffer
+               // check if it is a 2x modulate with framebuffer
+               if (m->blendfunc2 == GL_SRC_COLOR)
                        scaler *= 0.5f;
        }
-       else
+       else if (m->blendfunc2 != GL_SRC_COLOR)
        {
                if (m->tex[0])
                {
@@ -1251,183 +1238,6 @@ void R_Mesh_Draw(const rmeshinfo_t *m)
                R_Mesh_Render();
 }
 
-void R_Mesh_Draw_NativeOnly(const rmeshinfo_t *m)
-{
-       // these are static because gcc runs out of virtual registers otherwise
-       static int i, j, overbright, *index;
-       static float *in, scaler;
-       static buf_mesh_t *mesh;
-       static buf_vertex_t *vert;
-       static buf_fcolor_t *fcolor;
-       static buf_texcoord_t *texcoord[MAX_TEXTUREUNITS];
-
-       if (!backendactive)
-               Sys_Error("R_Mesh_Draw: called when backend is not active\n");
-
-       if (m->index == NULL
-        || !m->numtriangles
-        || m->vertex == NULL
-        || !m->numverts)
-               Host_Error("R_Mesh_Draw: no triangles or verts\n");
-
-       // ignore meaningless alpha meshs
-       if (!m->depthwrite && m->blendfunc1 == GL_SRC_ALPHA && (m->blendfunc2 == GL_ONE || m->blendfunc2 == GL_ONE_MINUS_SRC_ALPHA))
-       {
-               if (m->color)
-               {
-                       for (i = 0, in = m->color + 3;i < m->numverts;i++, (int)in += m->colorstep)
-                               if (*in >= 0.01f)
-                                       break;
-                       if (i == m->numverts)
-                               return;
-               }
-               else if (m->ca < 0.01f)
-                       return;
-       }
-
-       // LordHavoc: removed this error condition because with floatcolors 0,
-       // the 3DFX driver works with very large meshs
-       // FIXME: we can work around this by falling back on non-array renderer if buffers are too big
-       //if (m->numtriangles > 1024 || m->numverts > 3072)
-       //{
-       //      Con_Printf("R_Mesh_Draw_NativeOnly: mesh too big for 3DFX drivers, rejected\n");
-       //      return;
-       //}
-
-       i = max(m->numtriangles * 3, m->numverts);
-       if (overflowedverts < i)
-               overflowedverts = i;
-
-       if (m->numtriangles > max_meshs || m->numverts > max_verts)
-       {
-               Con_Printf("R_Mesh_Draw_NativeOnly: mesh too big for current gl_mesh_maxtriangles setting, increasing limits\n");
-               return;
-       }
-
-       if (m->transparent)
-       {
-               overflowedtransverts += max(m->numtriangles * 3, m->numverts);
-               if (currenttransmesh >= max_transmeshs || (currenttranstriangle + m->numtriangles) > max_transmeshs || (currenttransvertex + m->numverts) > max_transverts)
-               {
-                       if (!transranout)
-                       {
-                               Con_Printf("R_Mesh_Draw_NativeOnly: ran out of room for transparent meshs\n");
-                               transranout = true;
-                       }
-                       return;
-               }
-
-               c_transmeshs++;
-               c_transtris += m->numtriangles;
-               vert = &buf_transvertex[currenttransvertex];
-               fcolor = &buf_transfcolor[currenttransvertex];
-               for (i = 0;i < backendunits;i++)
-                       texcoord[i] = &buf_transtexcoord[i][currenttransvertex];
-
-               // transmesh is only for storage of transparent meshs until they
-               // are inserted into the main mesh array
-               mesh = &buf_transmesh[currenttransmesh++];
-               mesh->firsttriangle = currenttranstriangle;
-               mesh->firstvert = currenttransvertex;
-               index = &buf_transtri[currenttranstriangle].index[0];
-               currenttranstriangle += m->numtriangles;
-               currenttransvertex += m->numverts;
-       }
-       else
-       {
-               if (currentmesh >= max_meshs || (currenttriangle + m->numtriangles) > max_batch || (currentvertex + m->numverts) > max_verts)
-                       R_Mesh_Render();
-
-               c_meshs++;
-               c_meshtris += m->numtriangles;
-               vert = &buf_vertex[currentvertex];
-               fcolor = &buf_fcolor[currentvertex];
-               for (i = 0;i < backendunits;i++)
-                       texcoord[i] = &buf_texcoord[i][currentvertex];
-
-               // opaque meshs are rendered directly
-               mesh = &buf_mesh[currentmesh++];
-               mesh->firsttriangle = currenttriangle;
-               mesh->firstvert = currentvertex;
-               index = &buf_tri[currenttriangle].index[0];
-               currenttriangle += m->numtriangles;
-               currentvertex += m->numverts;
-       }
-
-       // code shared for transparent and opaque meshs
-       memcpy(index, m->index, sizeof(int[3]) * m->numtriangles);
-       mesh->blendfunc1 = m->blendfunc1;
-       mesh->blendfunc2 = m->blendfunc2;
-       mesh->depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite);
-       mesh->depthtest = !m->depthdisable;
-       mesh->triangles = m->numtriangles;
-       mesh->verts = m->numverts;
-
-       overbright = false;
-       scaler = 1;
-       if (m->blendfunc2 == GL_SRC_COLOR)
-       {
-               if (m->blendfunc1 == GL_DST_COLOR) // 2x modulate with framebuffer
-                       scaler *= 0.5f;
-       }
-       else
-       {
-               if (m->tex[0])
-               {
-                       overbright = gl_combine.integer;
-                       if (overbright)
-                               scaler *= 0.25f;
-               }
-               scaler *= overbrightscale;
-       }
-
-       j = -1;
-       for (i = 0;i < backendunits;i++)
-       {
-               if ((mesh->textures[i] = m->tex[i]))
-                       j = i;
-               mesh->texturergbscale[i] = m->texrgbscale[i];
-               if (mesh->texturergbscale[i] != 1 && mesh->texturergbscale[i] != 2 && mesh->texturergbscale[i] != 4)
-                       mesh->texturergbscale[i] = 1;
-       }
-       if (overbright && j >= 0)
-               mesh->texturergbscale[j] = 4;
-
-       if (m->vertexstep != sizeof(buf_vertex_t))
-               Host_Error("R_Mesh_Draw_NativeOnly: unsupported vertexstep\n");
-       if (m->colorstep != sizeof(buf_fcolor_t))
-               Host_Error("R_Mesh_Draw_NativeOnly: unsupported colorstep\n");
-       if (m->color == NULL)
-               Host_Error("R_Mesh_Draw_NativeOnly: must provide color array\n");
-       for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++)
-       {
-               if (j >= backendunits)
-                       Sys_Error("R_Mesh_Draw_NativeOnly: texture %i supplied when there are only %i texture units\n", j + 1, backendunits);
-               if (m->texcoordstep[j] != sizeof(buf_texcoord_t))
-                       Host_Error("R_Mesh_Draw_NativeOnly: unsupported texcoordstep\n");
-       }
-
-       memcpy(vert, m->vertex, m->numverts * sizeof(buf_vertex_t));
-       for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++)
-               memcpy(&texcoord[j][0].t[0], m->texcoords[j], m->numverts * sizeof(buf_texcoord_t));
-
-       memcpy(fcolor, m->color, m->numverts * sizeof(buf_fcolor_t));
-
-       // do this as a second step because memcpy preloaded the cache, which we can't easily do
-       if (scaler != 1)
-       {
-               for (i = 0;i < m->numverts;i++)
-               {
-                       fcolor[i].c[0] *= scaler;
-                       fcolor[i].c[1] *= scaler;
-                       fcolor[i].c[2] *= scaler;
-               }
-       }
-
-       if (currenttriangle >= max_batch)
-               R_Mesh_Render();
-}
-
 // allocates space in geometry buffers, and fills in pointers to the buffers in passsed struct
 // (this is used for very high speed rendering, no copying)
 int R_Mesh_Draw_GetBuffer(rmeshbufferinfo_t *m)
@@ -1523,12 +1333,13 @@ int R_Mesh_Draw_GetBuffer(rmeshbufferinfo_t *m)
 
        overbright = false;
        scaler = 1;
-       if (m->blendfunc2 == GL_SRC_COLOR)
+       if (m->blendfunc1 == GL_DST_COLOR)
        {
-               if (m->blendfunc1 == GL_DST_COLOR) // 2x modulate with framebuffer
+               // check if it is a 2x modulate with framebuffer
+               if (m->blendfunc2 == GL_SRC_COLOR)
                        scaler *= 0.5f;
        }
-       else
+       else if (m->blendfunc2 != GL_SRC_COLOR)
        {
                if (m->tex[0])
                {