]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_backend.c
moved the GL_CloseLibrary call a bit
[xonotic/darkplaces.git] / gl_backend.c
index a50dd7e4b8358ce86536dae380ddebe4fdefb45e..b991a9e6de229cb7a2bd67778d4da1b9dce98276 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"};
@@ -13,7 +13,9 @@ cvar_t gl_lockarrays = {0, "gl_lockarrays", "1"};
 
 // this is used to increase gl_mesh_maxtriangles automatically if a mesh was
 // too large for the buffers in the previous frame
-int overflowedmeshtris = 0;
+int overflowedverts = 0;
+// increase transtriangles automatically too
+int overflowedtransverts = 0;
 
 int gl_maxdrawrangeelementsvertices;
 int gl_maxdrawrangeelementsindices;
@@ -168,6 +170,19 @@ static void gl_backend_start(void)
 {
        int i;
 
+       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\n", gl_mesh_maxtriangles.integer, gl_mesh_transtriangles.integer);
+       if (qglDrawRangeElements != NULL)
+               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;
        max_transverts = max_transmeshs * 3;
 
@@ -215,6 +230,8 @@ static void gl_backend_start(void)
 
 static void gl_backend_shutdown(void)
 {
+       Con_Printf("OpenGL Backend shutting down\n");
+
        if (resizingbuffers)
                Mem_EmptyPool(gl_backend_mempool);
        else
@@ -226,30 +243,23 @@ static void gl_backend_shutdown(void)
 
 static void gl_backend_bufferchanges(int init)
 {
-       if (overflowedmeshtris > gl_mesh_maxtriangles.integer)
-               Cvar_SetValueQuick(&gl_mesh_maxtriangles, overflowedmeshtris);
-       overflowedmeshtris = 0;
+       if (overflowedverts > gl_mesh_maxtriangles.integer * 3)
+               Cvar_SetValueQuick(&gl_mesh_maxtriangles, (int) ((overflowedverts + 2) / 3));
+       overflowedverts = 0;
+
+       if (overflowedtransverts > gl_mesh_transtriangles.integer * 3)
+               Cvar_SetValueQuick(&gl_mesh_transtriangles, (int) ((overflowedtransverts + 2) / 3));
+       overflowedtransverts = 0;
 
        if (gl_mesh_drawmode.integer < 0)
                Cvar_SetValueQuick(&gl_mesh_drawmode, 0);
        if (gl_mesh_drawmode.integer > 3)
                Cvar_SetValueQuick(&gl_mesh_drawmode, 3);
 
-       if (gl_mesh_drawmode.integer >= 3)
+       if (gl_mesh_drawmode.integer >= 3 && qglDrawRangeElements == NULL)
        {
-               if (qglDrawRangeElements != NULL && gl_maxdrawrangeelementsindices >= 3072 && gl_maxdrawrangeelementsvertices >= 3072)
-               {
-                       // make sure we don't exceed the DrawRangeElements limits
-                       if (gl_mesh_maxtriangles.integer * 3 > gl_maxdrawrangeelementsindices)
-                               Cvar_SetValueQuick(&gl_mesh_maxtriangles, (int) (gl_maxdrawrangeelementsindices / 3));
-                       if (gl_mesh_maxtriangles.integer * 3 > gl_maxdrawrangeelementsvertices)
-                               Cvar_SetValueQuick(&gl_mesh_maxtriangles, (int) (gl_maxdrawrangeelementsvertices / 3));
-               }
-               else
-               {
-                       // change drawmode 3 to 2 if 3 won't work
-                       Cvar_SetValueQuick(&gl_mesh_drawmode, 2);
-               }
+               // change drawmode 3 to 2 if 3 won't work at all
+               Cvar_SetValueQuick(&gl_mesh_drawmode, 2);
        }
 
        // 21760 is (65536 / 3) rounded off to a multiple of 128
@@ -263,8 +273,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);
 
@@ -733,7 +743,7 @@ void GL_MeshState(buf_mesh_t *mesh)
 void GL_DrawRangeElements(int firstvert, int endvert, int indexcount, GLuint *index)
 {
        unsigned int i, j, in;
-       if (gl_mesh_drawmode.integer >= 3)
+       if (gl_mesh_drawmode.integer >= 3/* && (endvert - firstvert) <= gl_maxdrawrangeelementsvertices && (indexcount) <= gl_maxdrawrangeelementsindices*/)
        {
                // GL 1.2 or GL 1.1 with extension
                qglDrawRangeElements(GL_TRIANGLES, firstvert, endvert, indexcount, GL_UNSIGNED_INT, index);
@@ -858,7 +868,8 @@ void R_Mesh_Finish(void)
 {
        int i;
        // flush any queued meshs
-       R_Mesh_Render();
+       if (currentmesh)
+               R_Mesh_Render();
 
        if (backendunits > 1)
        {
@@ -1087,18 +1098,19 @@ void R_Mesh_Draw(const rmeshinfo_t *m)
        //      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: mesh too big for current gl_mesh_maxtriangles setting, increasing limits\n");
-               if (m->numtriangles > overflowedmeshtris)
-                       overflowedmeshtris = m->numtriangles;
-               if (((m->numverts + 2) / 3) > overflowedmeshtris)
-                       overflowedmeshtris = (m->numverts + 2) / 3;
                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)
@@ -1159,12 +1171,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])
                {
@@ -1245,182 +1258,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;
-       //}
-
-       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");
-               if (m->numtriangles > overflowedmeshtris)
-                       overflowedmeshtris = m->numtriangles;
-               if (((m->numverts + 2) / 3) > overflowedmeshtris)
-                       overflowedmeshtris = (m->numverts + 2) / 3;
-               return;
-       }
-
-       if (m->transparent)
-       {
-               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)
@@ -1446,18 +1283,19 @@ int R_Mesh_Draw_GetBuffer(rmeshbufferinfo_t *m)
        //      return false;
        //}
 
+       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_GetBuffer: mesh too big for current gl_mesh_maxtriangles setting, increasing limits\n");
-               if (m->numtriangles > overflowedmeshtris)
-                       overflowedmeshtris = m->numtriangles;
-               if (((m->numverts + 2) / 3) > overflowedmeshtris)
-                       overflowedmeshtris = (m->numverts + 2) / 3;
                return false;
        }
 
        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)
@@ -1515,12 +1353,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])
                {