]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_backend.c
changed use of GL_ARB_fragment_shader and friends to the core GL 2.0
[xonotic/darkplaces.git] / gl_backend.c
index 14dc46eea2f1d4d45cdd8ace239e625fac698d82..494e657e5b8f601f0859a8ac843ae604dc238585 100644 (file)
@@ -1,6 +1,7 @@
 
 #include "quakedef.h"
 #include "cl_collision.h"
+#include "dpsoftrast.h"
 #ifdef SUPPORTD3D
 #include <d3d9.h>
 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
@@ -12,7 +13,6 @@ extern D3DCAPS9 vid_d3d9caps;
 cvar_t gl_mesh_drawrangeelements = {0, "gl_mesh_drawrangeelements", "1", "use glDrawRangeElements function if available instead of glDrawElements (for performance comparisons or bug testing)"};
 cvar_t gl_mesh_testmanualfeeding = {0, "gl_mesh_testmanualfeeding", "0", "use glBegin(GL_TRIANGLES);glTexCoord2f();glVertex3f();glEnd(); primitives instead of glDrawElements (useful to test for driver bugs with glDrawElements)"};
 cvar_t gl_mesh_prefer_short_elements = {CVAR_SAVE, "gl_mesh_prefer_short_elements", "1", "use GL_UNSIGNED_SHORT element arrays instead of GL_UNSIGNED_INT"};
-cvar_t gl_mesh_separatearrays = {0, "gl_mesh_separatearrays", "1", "use several separate vertex arrays rather than one combined stream"};
 cvar_t gl_paranoid = {0, "gl_paranoid", "0", "enables OpenGL error checking and other tests"};
 cvar_t gl_printcheckerror = {0, "gl_printcheckerror", "0", "prints all OpenGL error checks, useful to identify location of driver crashes"};
 
@@ -166,7 +166,6 @@ typedef struct gl_state_s
        void *preparevertices_tempdata;
        size_t preparevertices_tempdatamaxsize;
        r_meshbuffer_t *preparevertices_dynamicvertexbuffer;
-       r_vertexposition_t *preparevertices_vertexposition;
        r_vertexgeneric_t *preparevertices_vertexgeneric;
        r_vertexmesh_t *preparevertices_vertexmesh;
        int preparevertices_numvertices;
@@ -291,6 +290,12 @@ static void R_Mesh_SetUseVBO(void)
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_SOFT:
+               gl_state.usevbo_staticvertex = false;
+               gl_state.usevbo_staticindex = false;
+               gl_state.usevbo_dynamicvertex = false;
+               gl_state.usevbo_dynamicindex = false;
+               break;
        }
 }
 
@@ -328,6 +333,8 @@ static void gl_backend_start(void)
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_SOFT:
+               break;
        }
 }
 
@@ -354,6 +361,8 @@ static void gl_backend_shutdown(void)
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_SOFT:
+               break;
        }
 
        if (gl_state.preparevertices_tempdata)
@@ -398,6 +407,8 @@ static void gl_backend_devicelost(void)
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_SOFT:
+               break;
        }
        endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
        for (i = 0;i < endindex;i++)
@@ -430,6 +441,8 @@ static void gl_backend_devicelost(void)
                case RENDERPATH_D3D11:
                        Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                        break;
+               case RENDERPATH_SOFT:
+                       break;
                }
        }
 }
@@ -455,6 +468,8 @@ static void gl_backend_devicerestored(void)
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_SOFT:
+               break;
        }
 }
 
@@ -481,7 +496,7 @@ void gl_backend_init(void)
 
        for (i = 0;i < (POLYGONELEMENTS_MAXPOINTS - 2)*3;i++)
                polygonelement3i[i] = polygonelement3s[i];
-       for (i = 0;i < QUADELEMENTS_MAXQUADS*3;i++)
+       for (i = 0;i < QUADELEMENTS_MAXQUADS*6;i++)
                quadelement3i[i] = quadelement3s[i];
 
        Cvar_RegisterVariable(&r_render);
@@ -499,7 +514,6 @@ void gl_backend_init(void)
        Cvar_RegisterVariable(&gl_mesh_drawrangeelements);
        Cvar_RegisterVariable(&gl_mesh_testmanualfeeding);
        Cvar_RegisterVariable(&gl_mesh_prefer_short_elements);
-       Cvar_RegisterVariable(&gl_mesh_separatearrays);
 
        Cmd_AddCommand("gl_vbostats", GL_VBOStats_f, "prints a list of all buffer objects (vertex data and triangle elements) and total video memory used by them");
 
@@ -667,6 +681,7 @@ qboolean R_ScissorForBBox(const float *mins, const float *maxs, int *scissor)
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_SOFT:
                break;
        }
 
@@ -749,6 +764,7 @@ void R_Viewport_InitOrtho(r_viewport_t *v, const matrix4x4_t *cameramatrix, int
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_SOFT:
                break;
        case RENDERPATH_D3D9:
        case RENDERPATH_D3D10:
@@ -998,6 +1014,7 @@ void R_Viewport_InitRectSideView(r_viewport_t *v, const matrix4x4_t *cameramatri
        case RENDERPATH_CGGL:
        case RENDERPATH_GL13:
        case RENDERPATH_GL11:
+       case RENDERPATH_SOFT:
                break;
        case RENDERPATH_D3D9:
                m[5] *= -1;
@@ -1065,6 +1082,9 @@ void R_SetViewport(const r_viewport_t *v)
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_SOFT:
+               DPSOFTRAST_Viewport(v->x, v->y, v->width, v->height);
+               break;
        }
 
        // force an update of the derived matrices
@@ -1120,6 +1140,8 @@ int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colorte
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
                return 1;
+       case RENDERPATH_SOFT:
+               return 1;
        }
        return 0;
 }
@@ -1139,6 +1161,8 @@ void R_Mesh_DestroyFramebufferObject(int fbo)
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
                break;
+       case RENDERPATH_SOFT:
+               break;
        }
 }
 
@@ -1203,6 +1227,9 @@ void R_Mesh_ResetRenderTargets(void)
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_SOFT:
+               DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
+               break;
        }
 }
 
@@ -1262,6 +1289,21 @@ void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colo
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_SOFT:
+               if (fbo)
+               {
+                       int width, height;
+                       unsigned int *pointers[5];
+                       memset(pointers, 0, sizeof(pointers));
+                       for (i = 0;i < 5;i++)
+                               pointers[i] = textures[i] ? (unsigned int *)DPSOFTRAST_Texture_GetPixelPointer(textures[i]->texnum, 0) : NULL;
+                       width = DPSOFTRAST_Texture_GetWidth(textures[0] ? textures[0]->texnum : textures[4]->texnum, 0);
+                       height = DPSOFTRAST_Texture_GetHeight(textures[0] ? textures[0]->texnum : textures[4]->texnum, 0);
+                       DPSOFTRAST_SetRenderTargets(width, height, pointers[4], pointers[0], pointers[1], pointers[2], pointers[3]);
+               }
+               else
+                       DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
+               break;
        }
 }
 
@@ -1429,7 +1471,7 @@ static void GL_Backend_ResetState(void)
 
                if (vid.support.ext_framebuffer_object)
                {
-                       qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+                       //qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
                        qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
                }
 
@@ -1471,6 +1513,17 @@ static void GL_Backend_ResetState(void)
                }
                CHECKGLERROR
                break;
+       case RENDERPATH_SOFT:
+               DPSOFTRAST_ColorMask(1,1,1,1);
+               DPSOFTRAST_AlphaTest(gl_state.alphatest);
+               DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
+               DPSOFTRAST_CullFace(gl_state.cullface);
+               DPSOFTRAST_DepthFunc(gl_state.depthfunc);
+               DPSOFTRAST_DepthMask(gl_state.depthmask);
+               DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
+               DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
+               DPSOFTRAST_Viewport(0, 0, vid.width, vid.height);
+               break;
        }
 }
 
@@ -1496,6 +1549,8 @@ void GL_ActiveTexture(unsigned int num)
                case RENDERPATH_D3D10:
                case RENDERPATH_D3D11:
                        break;
+               case RENDERPATH_SOFT:
+                       break;
                }
        }
 }
@@ -1522,6 +1577,8 @@ void GL_ClientActiveTexture(unsigned int num)
                case RENDERPATH_D3D10:
                case RENDERPATH_D3D11:
                        break;
+               case RENDERPATH_SOFT:
+                       break;
                }
        }
 }
@@ -1595,6 +1652,9 @@ void GL_BlendFunc(int blendfunc1, int blendfunc2)
                case RENDERPATH_D3D11:
                        Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                        break;
+               case RENDERPATH_SOFT:
+                       DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
+                       break;
                }
        }
 }
@@ -1624,6 +1684,9 @@ void GL_DepthMask(int state)
                case RENDERPATH_D3D11:
                        Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                        break;
+               case RENDERPATH_SOFT:
+                       DPSOFTRAST_DepthMask(gl_state.depthmask);
+                       break;
                }
        }
 }
@@ -1660,6 +1723,9 @@ void GL_DepthTest(int state)
                case RENDERPATH_D3D11:
                        Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                        break;
+               case RENDERPATH_SOFT:
+                       DPSOFTRAST_DepthTest(gl_state.depthtest);
+                       break;
                }
        }
 }
@@ -1689,6 +1755,9 @@ void GL_DepthFunc(int state)
                case RENDERPATH_D3D11:
                        Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                        break;
+               case RENDERPATH_SOFT:
+                       DPSOFTRAST_DepthFunc(gl_state.depthfunc);
+                       break;
                }
        }
 }
@@ -1727,6 +1796,9 @@ void GL_DepthRange(float nearfrac, float farfrac)
                case RENDERPATH_D3D11:
                        Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                        break;
+               case RENDERPATH_SOFT:
+                       DPSOFTRAST_DepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
+                       break;
                }
        }
 }
@@ -1791,6 +1863,9 @@ void R_SetStencilSeparate(qboolean enable, int writemask, int frontfail, int fro
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_SOFT:
+               //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+               break;
        }
 }
 
@@ -1840,6 +1915,9 @@ void R_SetStencil(qboolean enable, int writemask, int fail, int zfail, int zpass
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_SOFT:
+               //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+               break;
        }
 }
 
@@ -1869,6 +1947,9 @@ void GL_PolygonOffset(float planeoffset, float depthoffset)
                case RENDERPATH_D3D11:
                        Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                        break;
+               case RENDERPATH_SOFT:
+                       DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
+                       break;
                }
        }
 }
@@ -1903,6 +1984,9 @@ void GL_SetMirrorState(qboolean state)
                case RENDERPATH_D3D11:
                        Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                        break;
+               case RENDERPATH_SOFT:
+                       DPSOFTRAST_CullFace(gl_state.cullface);
+                       break;
                }
        }
 }
@@ -1976,6 +2060,14 @@ void GL_CullFace(int state)
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_SOFT:
+               if (gl_state.cullface != state)
+               {
+                       gl_state.cullface = state;
+                       gl_state.cullfaceenable = state != GL_NONE ? true : false;
+                       DPSOFTRAST_CullFace(gl_state.cullface);
+               }
+               break;
        }
 }
 
@@ -2011,6 +2103,9 @@ void GL_AlphaTest(int state)
                case RENDERPATH_D3D11:
                        Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                        break;
+               case RENDERPATH_SOFT:
+                       DPSOFTRAST_AlphaTest(gl_state.alphatest);
+                       break;
                }
        }
 }
@@ -2042,6 +2137,9 @@ void GL_AlphaFunc(int state, float value)
                case RENDERPATH_D3D11:
                        Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                        break;
+               case RENDERPATH_SOFT:
+                       DPSOFTRAST_AlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);
+                       break;
                }
        }
 }
@@ -2073,6 +2171,9 @@ void GL_ColorMask(int r, int g, int b, int a)
                case RENDERPATH_D3D11:
                        Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                        break;
+               case RENDERPATH_SOFT:
+                       DPSOFTRAST_ColorMask(r, g, b, a);
+                       break;
                }
        }
 }
@@ -2100,6 +2201,9 @@ void GL_Color(float cr, float cg, float cb, float ca)
                case RENDERPATH_D3D11:
                        // no equivalent in D3D
                        break;
+               case RENDERPATH_SOFT:
+                       DPSOFTRAST_Color4f(cr, cg, cb, ca);
+                       break;
                }
        }
 }
@@ -2134,6 +2238,9 @@ void GL_Scissor (int x, int y, int width, int height)
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_SOFT:
+               DPSOFTRAST_Scissor(x, y, width, height);
+               break;
        }
 }
 
@@ -2166,6 +2273,9 @@ void GL_ScissorTest(int state)
                case RENDERPATH_D3D11:
                        Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                        break;
+               case RENDERPATH_SOFT:
+                       DPSOFTRAST_ScissorTest(gl_state.scissortest);
+                       break;
                }
        }
 }
@@ -2213,6 +2323,12 @@ void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilva
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_SOFT:
+               if (mask & GL_COLOR_BUFFER_BIT)
+                       DPSOFTRAST_ClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);
+               if (mask & GL_DEPTH_BUFFER_BIT)
+                       DPSOFTRAST_ClearDepth(depthvalue);
+               break;
        }
 }
 
@@ -2269,6 +2385,9 @@ void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpi
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_SOFT:
+               DPSOFTRAST_GetPixelsBGRA(x, y, width, height, outpixels);
+               break;
        }
 }
 
@@ -2290,13 +2409,13 @@ qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, cons
        int shaderobject;
        int shadercompiled;
        char compilelog[MAX_INPUTLINE];
-       shaderobject = qglCreateShaderObjectARB(shadertypeenum);CHECKGLERROR
+       shaderobject = qglCreateShader(shadertypeenum);CHECKGLERROR
        if (!shaderobject)
                return false;
-       qglShaderSourceARB(shaderobject, numstrings, strings, NULL);CHECKGLERROR
-       qglCompileShaderARB(shaderobject);CHECKGLERROR
-       qglGetObjectParameterivARB(shaderobject, GL_OBJECT_COMPILE_STATUS_ARB, &shadercompiled);CHECKGLERROR
-       qglGetInfoLogARB(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
+       qglShaderSource(shaderobject, numstrings, strings, NULL);CHECKGLERROR
+       qglCompileShader(shaderobject);CHECKGLERROR
+       qglGetShaderiv(shaderobject, GL_COMPILE_STATUS, &shadercompiled);CHECKGLERROR
+       qglGetShaderInfoLog(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
        if (compilelog[0] && (strstr(compilelog, "error") || strstr(compilelog, "ERROR") || strstr(compilelog, "Error") || strstr(compilelog, "WARNING") || strstr(compilelog, "warning") || strstr(compilelog, "Warning")))
        {
                int i, j, pretextlines = 0;
@@ -2308,11 +2427,11 @@ qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, cons
        }
        if (!shadercompiled)
        {
-               qglDeleteObjectARB(shaderobject);CHECKGLERROR
+               qglDeleteShader(shaderobject);CHECKGLERROR
                return false;
        }
-       qglAttachObjectARB(programobject, shaderobject);CHECKGLERROR
-       qglDeleteObjectARB(shaderobject);CHECKGLERROR
+       qglAttachShader(programobject, shaderobject);CHECKGLERROR
+       qglDeleteShader(shaderobject);CHECKGLERROR
        return true;
 }
 
@@ -2323,24 +2442,24 @@ unsigned int GL_Backend_CompileProgram(int vertexstrings_count, const char **ver
        char linklog[MAX_INPUTLINE];
        CHECKGLERROR
 
-       programobject = qglCreateProgramObjectARB();CHECKGLERROR
+       programobject = qglCreateProgram();CHECKGLERROR
        if (!programobject)
                return 0;
 
-       if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER_ARB, "vertex", vertexstrings_count, vertexstrings_list))
+       if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER, "vertex", vertexstrings_count, vertexstrings_list))
                goto cleanup;
 
-#ifdef GL_GEOMETRY_SHADER_ARB
-       if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER_ARB, "geometry", geometrystrings_count, geometrystrings_list))
+#ifdef GL_GEOMETRY_SHADER
+       if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER, "geometry", geometrystrings_count, geometrystrings_list))
                goto cleanup;
 #endif
 
-       if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER_ARB, "fragment", fragmentstrings_count, fragmentstrings_list))
+       if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER, "fragment", fragmentstrings_count, fragmentstrings_list))
                goto cleanup;
 
-       qglLinkProgramARB(programobject);CHECKGLERROR
-       qglGetObjectParameterivARB(programobject, GL_OBJECT_LINK_STATUS_ARB, &programlinked);CHECKGLERROR
-       qglGetInfoLogARB(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
+       qglLinkProgram(programobject);CHECKGLERROR
+       qglGetProgramiv(programobject, GL_LINK_STATUS, &programlinked);CHECKGLERROR
+       qglGetProgramInfoLog(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
        if (linklog[0])
        {
                if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning"))
@@ -2358,14 +2477,14 @@ unsigned int GL_Backend_CompileProgram(int vertexstrings_count, const char **ver
                goto cleanup;
        return programobject;
 cleanup:
-       qglDeleteObjectARB(programobject);CHECKGLERROR
+       qglDeleteProgram(programobject);CHECKGLERROR
        return 0;
 }
 
 void GL_Backend_FreeProgram(unsigned int prog)
 {
        CHECKGLERROR
-       qglDeleteObjectARB(prog);
+       qglDeleteProgram(prog);
        CHECKGLERROR
 }
 
@@ -2429,6 +2548,8 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
                break;
+       case RENDERPATH_SOFT:
+               break;
        }
        // upload a dynamic index buffer if needed
        if (element3s)
@@ -2459,8 +2580,9 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri
        bufferoffset3i = element3i_bufferoffset;
        bufferobject3s = element3s_indexbuffer ? element3s_indexbuffer->bufferobject : 0;
        bufferoffset3s = element3s_bufferoffset;
-       r_refdef.stats.meshes++;
-       r_refdef.stats.meshes_elements += numelements;
+       r_refdef.stats.draws++;
+       r_refdef.stats.draws_vertices += numvertices;
+       r_refdef.stats.draws_elements += numelements;
        if (gl_paranoid.integer)
        {
                unsigned int i;
@@ -2740,11 +2862,11 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri
                        else
                        {
                                if (element3s)
-                                       IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3s + firsttriangle*3, D3DFMT_INDEX16, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
+                                       IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3s, D3DFMT_INDEX16, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
                                else if (element3i)
-                                       IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3i + firsttriangle*3, D3DFMT_INDEX32, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
+                                       IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3i, D3DFMT_INDEX32, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
                                else
-                                       IDirect3DDevice9_DrawPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, numvertices, (void *) ((byte *) gl_state.d3dvertexdata + (numvertices * gl_state.d3dvertexsize)), gl_state.d3dvertexsize);
+                                       IDirect3DDevice9_DrawPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, numvertices, (void *)gl_state.d3dvertexdata, gl_state.d3dvertexsize);
                        }
 #endif
                        break;
@@ -2754,6 +2876,9 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri
                case RENDERPATH_D3D11:
                        Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                        break;
+               case RENDERPATH_SOFT:
+                       DPSOFTRAST_DrawTriangles(firstvertex, numvertices, numtriangles, element3i, element3s);
+                       break;
                }
        }
 }
@@ -2868,6 +2993,8 @@ void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t si
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_SOFT:
+               break;
        }
 }
 
@@ -2903,6 +3030,8 @@ void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_SOFT:
+               break;
        }
        Mem_ExpandableArray_FreeRecord(&gl_state.meshbufferarray, (void *)buffer);
 }
@@ -3087,6 +3216,9 @@ void R_Mesh_CopyToTexture(rtexture_t *tex, int tx, int ty, int sx, int sy, int w
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_SOFT:
+               DPSOFTRAST_CopyRectangleToTexture(tex->texnum, 0, tx, ty, sx, sy, width, height);
+               break;
        }
 }
 
@@ -3246,6 +3378,19 @@ void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_SOFT:
+               if (!tex)
+               {
+                       tex = r_texture_white;
+                       // not initialized enough yet...
+                       if (!tex)
+                               return;
+               }
+               if (unit->texture == tex)
+                       return;
+               unit->texture = tex;
+               DPSOFTRAST_SetTexture(unitnum, R_GetTexture(tex));
+               break;
        }
 }
 
@@ -3293,6 +3438,8 @@ void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
                break;
+       case RENDERPATH_SOFT:
+               break;
        }
 }
 
@@ -3377,6 +3524,8 @@ void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, i
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
                break;
+       case RENDERPATH_SOFT:
+               break;
        }
 }
 
@@ -3492,19 +3641,21 @@ void R_Mesh_ResetTextureState(void)
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
                break;
+       case RENDERPATH_SOFT:
+               break;
        }
 }
 
 
 
 #ifdef SUPPORTD3D
-//#define r_vertexposition_d3d9fvf (D3DFVF_XYZ)
+//#define r_vertex3f_d3d9fvf (D3DFVF_XYZ)
 //#define r_vertexgeneric_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
 //#define r_vertexmesh_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX5 | D3DFVF_TEXCOORDSIZE1(3) | D3DFVF_TEXCOORDSIZE2(3) | D3DFVF_TEXCOORDSIZE3(3))
 
-D3DVERTEXELEMENT9 r_vertexposition_d3d9elements[] =
+D3DVERTEXELEMENT9 r_vertex3f_d3d9elements[] =
 {
-       {0, (int)((size_t)&((r_vertexposition_t *)0)->vertex3f), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
+       {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
        D3DDECL_END()
 };
 
@@ -3528,7 +3679,7 @@ D3DVERTEXELEMENT9 r_vertexmesh_d3d9elements[] =
        D3DDECL_END()
 };
 
-IDirect3DVertexDeclaration9 *r_vertexposition_d3d9decl;
+IDirect3DVertexDeclaration9 *r_vertex3f_d3d9decl;
 IDirect3DVertexDeclaration9 *r_vertexgeneric_d3d9decl;
 IDirect3DVertexDeclaration9 *r_vertexmesh_d3d9decl;
 #endif
@@ -3536,7 +3687,7 @@ IDirect3DVertexDeclaration9 *r_vertexmesh_d3d9decl;
 static void R_Mesh_InitVertexDeclarations(void)
 {
 #ifdef SUPPORTD3D
-       r_vertexposition_d3d9decl = NULL;
+       r_vertex3f_d3d9decl = NULL;
        r_vertexgeneric_d3d9decl = NULL;
        r_vertexmesh_d3d9decl = NULL;
        switch(vid.renderpath)
@@ -3547,7 +3698,7 @@ static void R_Mesh_InitVertexDeclarations(void)
        case RENDERPATH_GL11:
                break;
        case RENDERPATH_D3D9:
-               IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexposition_d3d9elements, &r_vertexposition_d3d9decl);
+               IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9elements, &r_vertex3f_d3d9decl);
                IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9elements, &r_vertexgeneric_d3d9decl);
                IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9elements, &r_vertexmesh_d3d9decl);
                break;
@@ -3557,6 +3708,8 @@ static void R_Mesh_InitVertexDeclarations(void)
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_SOFT:
+               break;
        }
 #endif
 }
@@ -3564,9 +3717,9 @@ static void R_Mesh_InitVertexDeclarations(void)
 static void R_Mesh_DestroyVertexDeclarations(void)
 {
 #ifdef SUPPORTD3D
-       if (r_vertexposition_d3d9decl)
-               IDirect3DVertexDeclaration9_Release(r_vertexposition_d3d9decl);
-       r_vertexposition_d3d9decl = NULL;
+       if (r_vertex3f_d3d9decl)
+               IDirect3DVertexDeclaration9_Release(r_vertex3f_d3d9decl);
+       r_vertex3f_d3d9decl = NULL;
        if (r_vertexgeneric_d3d9decl)
                IDirect3DVertexDeclaration9_Release(r_vertexgeneric_d3d9decl);
        r_vertexgeneric_d3d9decl = NULL;
@@ -3576,78 +3729,7 @@ static void R_Mesh_DestroyVertexDeclarations(void)
 #endif
 }
 
-r_vertexposition_t *R_Mesh_PrepareVertices_Position_Lock(int numvertices)
-{
-       size_t size;
-       size = sizeof(r_vertexposition_t) * numvertices;
-       if (gl_state.preparevertices_tempdatamaxsize < size)
-       {
-               gl_state.preparevertices_tempdatamaxsize = size;
-               gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
-       }
-       gl_state.preparevertices_vertexposition = (r_vertexposition_t *)gl_state.preparevertices_tempdata;
-       gl_state.preparevertices_numvertices = numvertices;
-       return gl_state.preparevertices_vertexposition;
-}
-
-qboolean R_Mesh_PrepareVertices_Position_Unlock(void)
-{
-       R_Mesh_PrepareVertices_Position(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexposition, NULL);
-       gl_state.preparevertices_vertexposition = NULL;
-       gl_state.preparevertices_numvertices = 0;
-       return true;
-}
-
-void R_Mesh_PrepareVertices_Position_Arrays(int numvertices, const float *vertex3f)
-{
-       int i;
-       r_vertexposition_t *vertex;
-       switch(vid.renderpath)
-       {
-       case RENDERPATH_GL20:
-       case RENDERPATH_CGGL:
-               R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
-               R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
-               R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
-               R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
-               R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
-               R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
-               R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
-               return;
-       case RENDERPATH_GL13:
-       case RENDERPATH_GL11:
-               R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
-               R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
-               R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
-               if (vid.texunits >= 2)
-                       R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
-               if (vid.texunits >= 3)
-                       R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
-               return;
-       case RENDERPATH_D3D9:
-#ifdef SUPPORTD3D
-               gl_state.d3dvertexbuffer = NULL;
-               gl_state.d3dvertexdata = (void *)vertex3f;
-               gl_state.d3dvertexsize = sizeof(float[3]);
-#endif
-               return;
-       case RENDERPATH_D3D10:
-               Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
-               break;
-       case RENDERPATH_D3D11:
-               Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
-               break;
-       }
-
-       // no quick path for this case, convert to vertex structs
-       vertex = R_Mesh_PrepareVertices_Position_Lock(numvertices);
-       for (i = 0;i < numvertices;i++)
-               VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
-       R_Mesh_PrepareVertices_Position_Unlock();
-       R_Mesh_PrepareVertices_Position(numvertices, vertex, NULL);
-}
-
-void R_Mesh_PrepareVertices_Position(int numvertices, const r_vertexposition_t *vertex, const r_meshbuffer_t *vertexbuffer)
+void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, const r_meshbuffer_t *vertexbuffer)
 {
        // upload temporary vertexbuffer for this rendering
        if (!gl_state.usevbo_staticvertex)
@@ -3655,9 +3737,9 @@ void R_Mesh_PrepareVertices_Position(int numvertices, const r_vertexposition_t *
        if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
        {
                if (gl_state.preparevertices_dynamicvertexbuffer)
-                       R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
+                       R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex3f, numvertices * sizeof(float[3]));
                else
-                       gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
+                       gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex3f, numvertices * sizeof(float[3]), "temporary", false, true, false);
                vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
        }
        switch(vid.renderpath)
@@ -3666,7 +3748,7 @@ void R_Mesh_PrepareVertices_Position(int numvertices, const r_vertexposition_t *
        case RENDERPATH_CGGL:
                if (vertexbuffer)
                {
-                       R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
+                       R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
                        R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
                        R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
                        R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
@@ -3676,7 +3758,7 @@ void R_Mesh_PrepareVertices_Position(int numvertices, const r_vertexposition_t *
                }
                else
                {
-                       R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , NULL, 0);
+                       R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
                        R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
                        R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
                        R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
@@ -3688,14 +3770,14 @@ void R_Mesh_PrepareVertices_Position(int numvertices, const r_vertexposition_t *
        case RENDERPATH_GL13:
                if (vertexbuffer)
                {
-                       R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
+                       R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
                        R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
                        R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
                        R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
                }
                else
                {
-                       R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , NULL, 0);
+                       R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
                        R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
                        R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
                        R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
@@ -3704,27 +3786,27 @@ void R_Mesh_PrepareVertices_Position(int numvertices, const r_vertexposition_t *
        case RENDERPATH_GL11:
                if (vertexbuffer)
                {
-                       R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
+                       R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
                        R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
                        R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
                }
                else
                {
-                       R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , NULL, 0);
+                       R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
                        R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
                        R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
                }
                break;
        case RENDERPATH_D3D9:
 #ifdef SUPPORTD3D
-               IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexposition_d3d9decl);
+               IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9decl);
                if (vertexbuffer)
-                       IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
+                       IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(float[3]));
                else
                        IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
                gl_state.d3dvertexbuffer = (void *)vertexbuffer;
-               gl_state.d3dvertexdata = (void *)vertex;
-               gl_state.d3dvertexsize = sizeof(*vertex);
+               gl_state.d3dvertexdata = (void *)vertex3f;
+               gl_state.d3dvertexsize = sizeof(float[3]);
 #endif
                break;
        case RENDERPATH_D3D10:
@@ -3733,6 +3815,15 @@ void R_Mesh_PrepareVertices_Position(int numvertices, const r_vertexposition_t *
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_SOFT:
+               DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
+               DPSOFTRAST_SetColorPointer(NULL, 0);
+               DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), NULL);
+               DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
+               DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
+               DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
+               DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
+               break;
        }
 }
 
@@ -3768,7 +3859,7 @@ void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3
        {
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
-               if (gl_mesh_separatearrays.integer)
+               if (!vid.useinterleavedarrays)
                {
                        R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
                        R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
@@ -3782,7 +3873,7 @@ void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3
                break;
        case RENDERPATH_GL13:
        case RENDERPATH_GL11:
-               if (gl_mesh_separatearrays.integer)
+               if (!vid.useinterleavedarrays)
                {
                        R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
                        R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
@@ -3798,6 +3889,15 @@ void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
                break;
+       case RENDERPATH_SOFT:
+               DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
+               DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
+               DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoord2f);
+               DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
+               DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
+               DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
+               DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
+               return;
        }
 
        // no quick path for this case, convert to vertex structs
@@ -3914,6 +4014,15 @@ void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *ve
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_SOFT:
+               DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
+               DPSOFTRAST_SetColorPointer4ub(vertex->color4ub, sizeof(*vertex));
+               DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoord2f);
+               DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(*vertex), NULL);
+               DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(*vertex), NULL);
+               DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(*vertex), NULL);
+               DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), NULL);
+               break;
        }
 }
 
@@ -3949,7 +4058,7 @@ void R_Mesh_PrepareVertices_Mesh_Arrays(int numvertices, const float *vertex3f,
        {
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
-               if (gl_mesh_separatearrays.integer)
+               if (!vid.useinterleavedarrays)
                {
                        R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
                        R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
@@ -3963,7 +4072,7 @@ void R_Mesh_PrepareVertices_Mesh_Arrays(int numvertices, const float *vertex3f,
                break;
        case RENDERPATH_GL13:
        case RENDERPATH_GL11:
-               if (gl_mesh_separatearrays.integer)
+               if (!vid.useinterleavedarrays)
                {
                        R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
                        R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
@@ -3979,6 +4088,15 @@ void R_Mesh_PrepareVertices_Mesh_Arrays(int numvertices, const float *vertex3f,
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
                break;
+       case RENDERPATH_SOFT:
+               DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
+               DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
+               DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoordtexture2f);
+               DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(float[3]), svector3f);
+               DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(float[3]), tvector3f);
+               DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(float[3]), normal3f);
+               DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), texcoordlightmap2f);
+               return;
        }
 
        vertex = R_Mesh_PrepareVertices_Mesh_Lock(numvertices);
@@ -4106,5 +4224,14 @@ void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex,
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_SOFT:
+               DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
+               DPSOFTRAST_SetColorPointer4ub(vertex->color4ub, sizeof(*vertex));
+               DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoordtexture2f);
+               DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(*vertex), vertex->svector3f);
+               DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(*vertex), vertex->tvector3f);
+               DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(*vertex), vertex->normal3f);
+               DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), vertex->texcoordlightmap2f);
+               break;
        }
 }