]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_backend.c
fix compile of VM_Warning changes
[xonotic/darkplaces.git] / gl_backend.c
index 7bc929e9b60d5864a8ffbd84759cb4f8c69db2d2..c7fca532607aee46eca9de2eccad4ff0ca167dee 100644 (file)
@@ -8,6 +8,94 @@ extern LPDIRECT3DDEVICE9 vid_d3d9dev;
 extern D3DCAPS9 vid_d3d9caps;
 #endif
 
+// on GLES we have to use some proper #define's
+#ifndef GL_FRAMEBUFFER
+#define GL_FRAMEBUFFER                                   0x8D40
+#define GL_DEPTH_ATTACHMENT                              0x8D00
+#define GL_COLOR_ATTACHMENT0                             0x8CE0
+#define GL_INVALID_FRAMEBUFFER_OPERATION                 0x0506
+#endif
+#ifndef GL_COLOR_ATTACHMENT1
+#define GL_COLOR_ATTACHMENT1                             0x8CE1
+#define GL_COLOR_ATTACHMENT2                             0x8CE2
+#define GL_COLOR_ATTACHMENT3                             0x8CE3
+#define GL_COLOR_ATTACHMENT4                             0x8CE4
+#define GL_COLOR_ATTACHMENT5                             0x8CE5
+#define GL_COLOR_ATTACHMENT6                             0x8CE6
+#define GL_COLOR_ATTACHMENT7                             0x8CE7
+#define GL_COLOR_ATTACHMENT8                             0x8CE8
+#define GL_COLOR_ATTACHMENT9                             0x8CE9
+#define GL_COLOR_ATTACHMENT10                            0x8CEA
+#define GL_COLOR_ATTACHMENT11                            0x8CEB
+#define GL_COLOR_ATTACHMENT12                            0x8CEC
+#define GL_COLOR_ATTACHMENT13                            0x8CED
+#define GL_COLOR_ATTACHMENT14                            0x8CEE
+#define GL_COLOR_ATTACHMENT15                            0x8CEF
+#endif
+#ifndef GL_ARRAY_BUFFER
+#define GL_ARRAY_BUFFER               0x8892
+#define GL_ELEMENT_ARRAY_BUFFER       0x8893
+#endif
+//#ifndef GL_VERTEX_ARRAY
+//#define GL_VERTEX_ARRAY                              0x8074
+//#define GL_COLOR_ARRAY                               0x8076
+//#define GL_TEXTURE_COORD_ARRAY                       0x8078
+//#endif
+#ifndef GL_TEXTURE0
+#define GL_TEXTURE0                                    0x84C0
+#define GL_TEXTURE1                                    0x84C1
+#define GL_TEXTURE2                                    0x84C2
+#define GL_TEXTURE3                                    0x84C3
+#define GL_TEXTURE4                                    0x84C4
+#define GL_TEXTURE5                                    0x84C5
+#define GL_TEXTURE6                                    0x84C6
+#define GL_TEXTURE7                                    0x84C7
+#define GL_TEXTURE8                                    0x84C8
+#define GL_TEXTURE9                                    0x84C9
+#define GL_TEXTURE10                           0x84CA
+#define GL_TEXTURE11                           0x84CB
+#define GL_TEXTURE12                           0x84CC
+#define GL_TEXTURE13                           0x84CD
+#define GL_TEXTURE14                           0x84CE
+#define GL_TEXTURE15                           0x84CF
+#define GL_TEXTURE16                           0x84D0
+#define GL_TEXTURE17                           0x84D1
+#define GL_TEXTURE18                           0x84D2
+#define GL_TEXTURE19                           0x84D3
+#define GL_TEXTURE20                           0x84D4
+#define GL_TEXTURE21                           0x84D5
+#define GL_TEXTURE22                           0x84D6
+#define GL_TEXTURE23                           0x84D7
+#define GL_TEXTURE24                           0x84D8
+#define GL_TEXTURE25                           0x84D9
+#define GL_TEXTURE26                           0x84DA
+#define GL_TEXTURE27                           0x84DB
+#define GL_TEXTURE28                           0x84DC
+#define GL_TEXTURE29                           0x84DD
+#define GL_TEXTURE30                           0x84DE
+#define GL_TEXTURE31                           0x84DF
+#endif
+
+#ifndef GL_TEXTURE_3D
+#define GL_TEXTURE_3D                          0x806F
+#endif
+#ifndef GL_TEXTURE_CUBE_MAP
+#define GL_TEXTURE_CUBE_MAP                0x8513
+#endif
+//#ifndef GL_MODELVIEW
+//#define GL_MODELVIEW                         0x1700
+//#endif
+//#ifndef GL_PROJECTION
+//#define GL_PROJECTION                                0x1701
+//#endif
+//#ifndef GL_DECAL
+//#define GL_DECAL                             0x2101
+//#endif
+//#ifndef GL_INTERPOLATE
+//#define GL_INTERPOLATE                               0x8575
+//#endif
+
+
 #define MAX_RENDERTARGETS 4
 
 cvar_t gl_mesh_drawrangeelements = {0, "gl_mesh_drawrangeelements", "1", "use glDrawRangeElements function if available instead of glDrawElements (for performance comparisons or bug testing)"};
@@ -84,8 +172,8 @@ void GL_PrintError(int errornumber, const char *filename, int linenumber)
                Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
                break;
 #endif
-#ifdef GL_INVALID_FRAMEBUFFER_OPERATION_EXT
-       case GL_INVALID_FRAMEBUFFER_OPERATION_EXT:
+#ifdef GL_INVALID_FRAMEBUFFER_OPERATION
+       case GL_INVALID_FRAMEBUFFER_OPERATION:
                Con_Printf("GL_INVALID_FRAMEBUFFER_OPERATION at %s:%i\n", filename, linenumber);
                break;
 #endif
@@ -137,6 +225,7 @@ typedef struct gl_state_s
        int alphatest;
        int alphafunc;
        float alphafuncvalue;
+       qboolean alphatocoverage;
        int scissortest;
        unsigned int unit;
        unsigned int clientunit;
@@ -258,7 +347,7 @@ unsigned short polygonelement3s[(POLYGONELEMENTS_MAXPOINTS-2)*3];
 int quadelement3i[QUADELEMENTS_MAXQUADS*6];
 unsigned short quadelement3s[QUADELEMENTS_MAXQUADS*6];
 
-void GL_VBOStats_f(void)
+static void GL_VBOStats_f(void)
 {
        GL_Mesh_ListVBOs(true);
 }
@@ -275,6 +364,7 @@ static void R_Mesh_SetUseVBO(void)
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
+       case RENDERPATH_GLES1:
                gl_state.usevbo_staticvertex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
                gl_state.usevbo_staticindex = (vid.support.arb_vertex_buffer_object && (gl_vbo.integer == 1 || gl_vbo.integer == 3)) || vid.forcevbo;
                gl_state.usevbo_dynamicvertex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer) || vid.forcevbo;
@@ -325,10 +415,11 @@ static void gl_backend_start(void)
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
+       case RENDERPATH_GLES1:
        case RENDERPATH_GLES2:
                // fetch current fbo here (default fbo is not 0 on some GLES devices)
                if (vid.support.ext_framebuffer_object)
-                       qglGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &gl_state.defaultframebufferobject);
+                       qglGetIntegerv(GL_FRAMEBUFFER_BINDING, &gl_state.defaultframebufferobject);
                break;
        case RENDERPATH_D3D9:
 #ifdef SUPPORTD3D
@@ -357,6 +448,7 @@ static void gl_backend_shutdown(void)
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES1:
        case RENDERPATH_GLES2:
                break;
        case RENDERPATH_D3D9:
@@ -402,6 +494,7 @@ static void gl_backend_devicelost(void)
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES1:
        case RENDERPATH_GLES2:
                break;
        case RENDERPATH_D3D9:
@@ -429,6 +522,7 @@ static void gl_backend_devicelost(void)
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
                case RENDERPATH_SOFT:
+               case RENDERPATH_GLES1:
                case RENDERPATH_GLES2:
                        break;
                case RENDERPATH_D3D9:
@@ -461,6 +555,7 @@ static void gl_backend_devicerestored(void)
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES1:
        case RENDERPATH_GLES2:
                break;
        case RENDERPATH_D3D9:
@@ -550,6 +645,7 @@ void GL_Finish(void)
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
+       case RENDERPATH_GLES1:
        case RENDERPATH_GLES2:
                qglFinish();
                break;
@@ -711,6 +807,7 @@ qboolean R_ScissorForBBox(const float *mins, const float *maxs, int *scissor)
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES1:
        case RENDERPATH_GLES2:
                break;
        }
@@ -730,7 +827,7 @@ static void R_Viewport_ApplyNearClipPlaneFloatGL(const r_viewport_t *v, float *m
 
        VectorSet(normal, normalx, normaly, normalz);
        Matrix4x4_Transform3x3(&v->viewmatrix, normal, clipPlane);
-       VectorScale(normal, dist, v3);
+       VectorScale(normal, -dist, v3);
        Matrix4x4_Transform(&v->viewmatrix, v3, v4);
        // FIXME: LordHavoc: I think this can be done more efficiently somehow but I can't remember the technique
        clipPlane[3] = -DotProduct(v4, clipPlane);
@@ -794,6 +891,7 @@ void R_Viewport_InitOrtho(r_viewport_t *v, const matrix4x4_t *cameramatrix, int
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES1:
        case RENDERPATH_GLES2:
                break;
        case RENDERPATH_D3D9:
@@ -1044,6 +1142,7 @@ void R_Viewport_InitRectSideView(r_viewport_t *v, const matrix4x4_t *cameramatri
        case RENDERPATH_GL13:
        case RENDERPATH_GL11:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES1:
        case RENDERPATH_GLES2:
                break;
        case RENDERPATH_D3D9:
@@ -1079,6 +1178,8 @@ void R_SetViewport(const r_viewport_t *v)
        {
        case RENDERPATH_GL13:
        case RENDERPATH_GL11:
+       case RENDERPATH_GLES1:
+#ifdef GL_PROJECTION
                CHECKGLERROR
                qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
                // Load the projection matrix into OpenGL
@@ -1086,6 +1187,7 @@ void R_SetViewport(const r_viewport_t *v)
                Matrix4x4_ToArrayFloatGL(&gl_projectionmatrix, m);
                qglLoadMatrixf(m);CHECKGLERROR
                qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
+#endif
                break;
        case RENDERPATH_D3D9:
 #ifdef SUPPORTD3D
@@ -1133,7 +1235,7 @@ static void GL_BindVBO(int bufferobject)
        {
                gl_state.vertexbufferobject = bufferobject;
                CHECKGLERROR
-               qglBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR
+               qglBindBufferARB(GL_ARRAY_BUFFER, bufferobject);CHECKGLERROR
        }
 }
 
@@ -1143,29 +1245,74 @@ static void GL_BindEBO(int bufferobject)
        {
                gl_state.elementbufferobject = bufferobject;
                CHECKGLERROR
-               qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR
+               qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, bufferobject);CHECKGLERROR
        }
 }
 
+static const GLuint drawbuffers[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3};
 int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
 {
-       int temp;
        switch(vid.renderpath)
        {
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
+       case RENDERPATH_GLES1:
        case RENDERPATH_GLES2:
-               if (!vid.support.ext_framebuffer_object)
-                       return 0;
-               qglGenFramebuffersEXT(1, (GLuint*)&temp);CHECKGLERROR
-               R_Mesh_SetRenderTargets(temp, NULL, NULL, NULL, NULL, NULL);
-               if (depthtexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, depthtexture->gltexturetypeenum, R_GetTexture(depthtexture), 0);CHECKGLERROR
-               if (colortexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, colortexture->gltexturetypeenum, R_GetTexture(colortexture), 0);CHECKGLERROR
-               if (colortexture2) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, colortexture2->gltexturetypeenum, R_GetTexture(colortexture2), 0);CHECKGLERROR
-               if (colortexture3) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, colortexture3->gltexturetypeenum, R_GetTexture(colortexture3), 0);CHECKGLERROR
-               if (colortexture4) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT3_EXT, colortexture4->gltexturetypeenum, R_GetTexture(colortexture4), 0);CHECKGLERROR
-               return temp;
+               if (vid.support.ext_framebuffer_object)
+               {
+                       int temp;
+                       GLuint status;
+                       qglGenFramebuffersEXT(1, (GLuint*)&temp);CHECKGLERROR
+                       R_Mesh_SetRenderTargets(temp, NULL, NULL, NULL, NULL, NULL);
+                       if (depthtexture  && depthtexture->texnum ) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT  , depthtexture->gltexturetypeenum , depthtexture->texnum , 0);CHECKGLERROR
+               //      if (depthtexture  && depthtexture->texnum ) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthtexture->gltexturetypeenum , depthtexture->texnum , 0);CHECKGLERROR
+                       if (colortexture  && colortexture->texnum ) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 , colortexture->gltexturetypeenum , colortexture->texnum , 0);CHECKGLERROR
+                       if (colortexture2 && colortexture2->texnum) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1 , colortexture2->gltexturetypeenum, colortexture2->texnum, 0);CHECKGLERROR
+                       if (colortexture3 && colortexture3->texnum) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2 , colortexture3->gltexturetypeenum, colortexture3->texnum, 0);CHECKGLERROR
+                       if (colortexture4 && colortexture4->texnum) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3 , colortexture4->gltexturetypeenum, colortexture4->texnum, 0);CHECKGLERROR
+                       if (depthtexture  && depthtexture->renderbuffernum ) qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT  , GL_RENDERBUFFER, depthtexture->renderbuffernum );CHECKGLERROR
+                       if (depthtexture  && depthtexture->renderbuffernum ) qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthtexture->renderbuffernum );CHECKGLERROR
+                       if (colortexture  && colortexture->renderbuffernum ) qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 , GL_RENDERBUFFER, colortexture->renderbuffernum );CHECKGLERROR
+                       if (colortexture2 && colortexture2->renderbuffernum) qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1 , GL_RENDERBUFFER, colortexture2->renderbuffernum);CHECKGLERROR
+                       if (colortexture3 && colortexture3->renderbuffernum) qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2 , GL_RENDERBUFFER, colortexture3->renderbuffernum);CHECKGLERROR
+                       if (colortexture4 && colortexture4->renderbuffernum) qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3 , GL_RENDERBUFFER, colortexture4->renderbuffernum);CHECKGLERROR
+
+                       if (colortexture4 && qglDrawBuffersARB)
+                       {
+                               qglDrawBuffersARB(4, drawbuffers);CHECKGLERROR
+                               qglReadBuffer(GL_NONE);CHECKGLERROR
+                       }
+                       else if (colortexture3 && qglDrawBuffersARB)
+                       {
+                               qglDrawBuffersARB(3, drawbuffers);CHECKGLERROR
+                               qglReadBuffer(GL_NONE);CHECKGLERROR
+                       }
+                       else if (colortexture2 && qglDrawBuffersARB)
+                       {
+                               qglDrawBuffersARB(2, drawbuffers);CHECKGLERROR
+                               qglReadBuffer(GL_NONE);CHECKGLERROR
+                       }
+                       else if (colortexture && qglDrawBuffer)
+                       {
+                               qglDrawBuffer(drawbuffers[0]);CHECKGLERROR
+                               qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
+                       }
+                       else if (qglDrawBuffer)
+                       {
+                               qglDrawBuffer(GL_NONE);CHECKGLERROR
+                               qglReadBuffer(GL_NONE);CHECKGLERROR
+                       }
+                       status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
+                       if (status != GL_FRAMEBUFFER_COMPLETE)
+                       {
+                               Con_Printf("R_Mesh_CreateFramebufferObject: glCheckFramebufferStatusEXT returned %i\n", status);
+                               qglDeleteFramebuffersEXT(1, (GLuint*)&temp);
+                               temp = 0;
+                       }
+                       return temp;
+               }
+               return 0;
        case RENDERPATH_D3D9:
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
@@ -1183,6 +1330,7 @@ void R_Mesh_DestroyFramebufferObject(int fbo)
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
+       case RENDERPATH_GLES1:
        case RENDERPATH_GLES2:
                if (fbo)
                        qglDeleteFramebuffersEXT(1, (GLuint*)&fbo);
@@ -1199,10 +1347,6 @@ void R_Mesh_DestroyFramebufferObject(int fbo)
 #ifdef SUPPORTD3D
 void R_Mesh_SetRenderTargetsD3D9(IDirect3DSurface9 *depthsurface, IDirect3DSurface9 *colorsurface0, IDirect3DSurface9 *colorsurface1, IDirect3DSurface9 *colorsurface2, IDirect3DSurface9 *colorsurface3)
 {
-// LordHavoc: for some weird reason the redundant SetDepthStencilSurface calls are necessary (otherwise the lights fail depth test, as if they were using the shadowmap depth surface and render target still)
-       if (gl_state.d3drt_depthsurface == depthsurface && gl_state.d3drt_colorsurfaces[0] == colorsurface0 && gl_state.d3drt_colorsurfaces[1] == colorsurface1 && gl_state.d3drt_colorsurfaces[2] == colorsurface2 && gl_state.d3drt_colorsurfaces[3] == colorsurface3)
-               return;
-
        gl_state.framebufferobject = depthsurface != gl_state.d3drt_backbufferdepthsurface || colorsurface0 != gl_state.d3drt_backbuffercolorsurface;
        if (gl_state.d3drt_depthsurface != depthsurface)
        {
@@ -1232,37 +1376,6 @@ void R_Mesh_SetRenderTargetsD3D9(IDirect3DSurface9 *depthsurface, IDirect3DSurfa
 }
 #endif
 
-void R_Mesh_ResetRenderTargets(void)
-{
-       switch(vid.renderpath)
-       {
-       case RENDERPATH_GL11:
-       case RENDERPATH_GL13:
-       case RENDERPATH_GL20:
-       case RENDERPATH_GLES2:
-               if (gl_state.framebufferobject)
-               {
-                       gl_state.framebufferobject = 0;
-                       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.defaultframebufferobject);
-               }
-               break;
-       case RENDERPATH_D3D9:
-#ifdef SUPPORTD3D
-               R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
-#endif
-               break;
-       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;
-       case RENDERPATH_SOFT:
-               DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
-               break;
-       }
-}
-
 void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
 {
        unsigned int i;
@@ -1282,11 +1395,12 @@ void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colo
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
+       case RENDERPATH_GLES1:
        case RENDERPATH_GLES2:
                if (gl_state.framebufferobject != fbo)
                {
                        gl_state.framebufferobject = fbo;
-                       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject ? gl_state.framebufferobject : gl_state.defaultframebufferobject);
+                       qglBindFramebufferEXT(GL_FRAMEBUFFER, gl_state.framebufferobject ? gl_state.framebufferobject : gl_state.defaultframebufferobject);
                }
                break;
        case RENDERPATH_D3D9:
@@ -1295,19 +1409,24 @@ void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colo
                // TODO: optimize: keep surface pointer around in rtexture_t until texture is freed or lost
                if (fbo)
                {
-                       IDirect3DSurface9 *colorsurfaces[4];
-                       for (i = 0;i < 4;i++)
+                       IDirect3DSurface9 *surfaces[5];
+                       for (i = 0;i < 5;i++)
                        {
-                               colorsurfaces[i] = NULL;
+                               surfaces[i] = NULL;
                                if (textures[i])
-                                       IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9 *)textures[i]->d3dtexture, 0, &colorsurfaces[i]);
+                               {
+                                       if (textures[i]->d3dsurface)
+                                               surfaces[i] = (IDirect3DSurface9 *)textures[i]->d3dsurface;
+                                       else
+                                               IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9 *)textures[i]->d3dtexture, 0, &surfaces[i]);
+                               }
                        }
                        // set the render targets for real
-                       R_Mesh_SetRenderTargetsD3D9(depthtexture ? (IDirect3DSurface9 *)depthtexture->d3dtexture : NULL, colorsurfaces[0], colorsurfaces[1], colorsurfaces[2], colorsurfaces[3]);
+                       R_Mesh_SetRenderTargetsD3D9(surfaces[4], surfaces[0], surfaces[1], surfaces[2], surfaces[3]);
                        // release the texture surface levels (they won't be lost while bound...)
-                       for (i = 0;i < 4;i++)
-                               if (textures[i])
-                                       IDirect3DSurface9_Release(colorsurfaces[i]);
+                       for (i = 0;i < 5;i++)
+                               if (textures[i] && !textures[i]->d3dsurface)
+                                       IDirect3DSurface9_Release(surfaces[i]);
                }
                else
                        R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
@@ -1366,6 +1485,7 @@ static int d3dstencilopforglfunc(int f)
 }
 #endif
 
+extern cvar_t r_transparent_alphatocoverage;
 
 static void GL_Backend_ResetState(void)
 {
@@ -1375,6 +1495,7 @@ static void GL_Backend_ResetState(void)
        gl_state.alphatest = false;
        gl_state.alphafunc = GL_GEQUAL;
        gl_state.alphafuncvalue = 0.5f;
+       gl_state.alphatocoverage = false;
        gl_state.blendfunc1 = GL_ONE;
        gl_state.blendfunc2 = GL_ZERO;
        gl_state.blend = false;
@@ -1396,9 +1517,6 @@ static void GL_Backend_ResetState(void)
 #ifdef SUPPORTD3D
                {
                        IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, gl_state.colormask);
-                       IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHATESTENABLE, gl_state.alphatest);
-                       IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAFUNC, d3dcmpforglfunc(gl_state.alphafunc));
-                       IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAREF, (int)bound(0, gl_state.alphafuncvalue * 256.0f, 255));
                        IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
                        IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
                        IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
@@ -1414,8 +1532,10 @@ static void GL_Backend_ResetState(void)
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
-       case RENDERPATH_GL13:
        case RENDERPATH_GL11:
+       case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
+#ifdef GL_ALPHA_TEST
                CHECKGLERROR
 
                qglColorMask(1, 1, 1, 1);CHECKGLERROR
@@ -1432,14 +1552,14 @@ static void GL_Backend_ResetState(void)
 
                if (vid.support.arb_vertex_buffer_object)
                {
-                       qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
-                       qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+                       qglBindBufferARB(GL_ARRAY_BUFFER, 0);
+                       qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);
                }
 
                if (vid.support.ext_framebuffer_object)
                {
-                       //qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
-                       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+                       //qglBindRenderbufferEXT(GL_RENDERBUFFER, 0);
+                       qglBindFramebufferEXT(GL_FRAMEBUFFER, 0);
                }
 
                qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
@@ -1450,7 +1570,7 @@ static void GL_Backend_ResetState(void)
                qglColor4f(1, 1, 1, 1);CHECKGLERROR
 
                if (vid.support.ext_framebuffer_object)
-                       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject);
+                       qglBindFramebufferEXT(GL_FRAMEBUFFER, gl_state.framebufferobject);
 
                gl_state.unit = MAX_TEXTUREUNITS;
                gl_state.clientunit = MAX_TEXTUREUNITS;
@@ -1467,8 +1587,8 @@ static void GL_Backend_ResetState(void)
                        }
                        if (vid.support.arb_texture_cube_map)
                        {
-                               qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
-                               qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
+                               qglDisable(GL_TEXTURE_CUBE_MAP);CHECKGLERROR
+                               qglBindTexture(GL_TEXTURE_CUBE_MAP, 0);CHECKGLERROR
                        }
                        GL_BindVBO(0);
                        qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
@@ -1479,10 +1599,10 @@ static void GL_Backend_ResetState(void)
                        qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
                }
                CHECKGLERROR
+#endif
                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);
@@ -1503,18 +1623,13 @@ static void GL_Backend_ResetState(void)
                qglEnable(GL_DEPTH_TEST);CHECKGLERROR
                qglDepthMask(gl_state.depthmask);CHECKGLERROR
                qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
-       //      if (vid.renderpath == RENDERPATH_GL20)
-       //      {
-       //              qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
-       //              qglDisable(GL_ALPHA_TEST);CHECKGLERROR
-       //      }
                if (vid.support.arb_vertex_buffer_object)
                {
-                       qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
-                       qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+                       qglBindBufferARB(GL_ARRAY_BUFFER, 0);
+                       qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);
                }
                if (vid.support.ext_framebuffer_object)
-                       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.defaultframebufferobject);
+                       qglBindFramebufferEXT(GL_FRAMEBUFFER, gl_state.defaultframebufferobject);
                qglEnableVertexAttribArray(GLSLATTRIB_POSITION);
                qglVertexAttribPointer(GLSLATTRIB_POSITION, 3, GL_FLOAT, false, sizeof(float[3]), NULL);CHECKGLERROR
                qglDisableVertexAttribArray(GLSLATTRIB_COLOR);
@@ -1532,7 +1647,7 @@ static void GL_Backend_ResetState(void)
                        }
                        if (vid.support.arb_texture_cube_map)
                        {
-                               qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
+                               qglBindTexture(GL_TEXTURE_CUBE_MAP, 0);CHECKGLERROR
                        }
                }
                for (i = 0;i < vid.texarrayunits;i++)
@@ -1556,11 +1671,12 @@ void GL_ActiveTexture(unsigned int num)
                case RENDERPATH_GL11:
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
+               case RENDERPATH_GLES1:
                case RENDERPATH_GLES2:
                        if (qglActiveTexture)
                        {
                                CHECKGLERROR
-                               qglActiveTexture(GL_TEXTURE0_ARB + gl_state.unit);
+                               qglActiveTexture(GL_TEXTURE0 + gl_state.unit);
                                CHECKGLERROR
                        }
                        break;
@@ -1583,10 +1699,11 @@ void GL_ClientActiveTexture(unsigned int num)
                {
                case RENDERPATH_GL11:
                case RENDERPATH_GL13:
+               case RENDERPATH_GLES1:
                        if (qglActiveTexture)
                        {
                                CHECKGLERROR
-                               qglClientActiveTexture(GL_TEXTURE0_ARB + gl_state.clientunit);
+                               qglClientActiveTexture(GL_TEXTURE0 + gl_state.clientunit);
                                CHECKGLERROR
                        }
                        break;
@@ -1616,6 +1733,7 @@ void GL_BlendFunc(int blendfunc1, int blendfunc2)
                case RENDERPATH_GL11:
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
+               case RENDERPATH_GLES1:
                case RENDERPATH_GLES2:
                        CHECKGLERROR
                        qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
@@ -1689,6 +1807,7 @@ void GL_DepthMask(int state)
                case RENDERPATH_GL11:
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
+               case RENDERPATH_GLES1:
                case RENDERPATH_GLES2:
                        CHECKGLERROR
                        qglDepthMask(gl_state.depthmask);CHECKGLERROR
@@ -1721,6 +1840,7 @@ void GL_DepthTest(int state)
                case RENDERPATH_GL11:
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
+               case RENDERPATH_GLES1:
                case RENDERPATH_GLES2:
                        CHECKGLERROR
                        if (gl_state.depthtest)
@@ -1760,6 +1880,7 @@ void GL_DepthFunc(int state)
                case RENDERPATH_GL11:
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
+               case RENDERPATH_GLES1:
                case RENDERPATH_GLES2:
                        CHECKGLERROR
                        qglDepthFunc(gl_state.depthfunc);CHECKGLERROR
@@ -1793,8 +1914,13 @@ void GL_DepthRange(float nearfrac, float farfrac)
                case RENDERPATH_GL11:
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
+               case RENDERPATH_GLES1:
                case RENDERPATH_GLES2:
+#ifdef USE_GLES2
+                       qglDepthRangef(gl_state.depthrange[0], gl_state.depthrange[1]);
+#else
                        qglDepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
+#endif
                        break;
                case RENDERPATH_D3D9:
 #ifdef SUPPORTD3D
@@ -1830,6 +1956,7 @@ void R_SetStencilSeparate(qboolean enable, int writemask, int frontfail, int fro
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
+       case RENDERPATH_GLES1:
        case RENDERPATH_GLES2:
                CHECKGLERROR
                if (enable)
@@ -1849,6 +1976,7 @@ void R_SetStencilSeparate(qboolean enable, int writemask, int frontfail, int fro
                }
                else if (vid.support.ext_stencil_two_side)
                {
+#ifdef GL_STENCIL_TEST_TWO_SIDE_EXT
                        qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
                        qglActiveStencilFaceEXT(GL_FRONT);CHECKGLERROR
                        qglStencilMask(writemask);CHECKGLERROR
@@ -1858,6 +1986,7 @@ void R_SetStencilSeparate(qboolean enable, int writemask, int frontfail, int fro
                        qglStencilMask(writemask);CHECKGLERROR
                        qglStencilOp(backfail, backzfail, backzpass);CHECKGLERROR
                        qglStencilFunc(backcompare, comparereference, comparemask);CHECKGLERROR
+#endif
                }
                break;
        case RENDERPATH_D3D9:
@@ -1896,6 +2025,7 @@ void R_SetStencil(qboolean enable, int writemask, int fail, int zfail, int zpass
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
+       case RENDERPATH_GLES1:
        case RENDERPATH_GLES2:
                CHECKGLERROR
                if (enable)
@@ -1908,7 +2038,9 @@ void R_SetStencil(qboolean enable, int writemask, int fail, int zfail, int zpass
                }
                if (vid.support.ext_stencil_two_side)
                {
+#ifdef GL_STENCIL_TEST_TWO_SIDE_EXT
                        qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
+#endif
                }
                qglStencilMask(writemask);CHECKGLERROR
                qglStencilOp(fail, zfail, zpass);CHECKGLERROR
@@ -1952,6 +2084,7 @@ void GL_PolygonOffset(float planeoffset, float depthoffset)
                case RENDERPATH_GL11:
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
+               case RENDERPATH_GLES1:
                case RENDERPATH_GLES2:
                        qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
                        break;
@@ -1990,6 +2123,7 @@ void GL_SetMirrorState(qboolean state)
                case RENDERPATH_GL11:
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
+               case RENDERPATH_GLES1:
                case RENDERPATH_GLES2:
                        qglCullFace(gl_state.cullface);CHECKGLERROR
                        break;
@@ -2026,6 +2160,7 @@ void GL_CullFace(int state)
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
+       case RENDERPATH_GLES1:
        case RENDERPATH_GLES2:
                CHECKGLERROR
 
@@ -2100,6 +2235,8 @@ void GL_AlphaTest(int state)
                {
                case RENDERPATH_GL11:
                case RENDERPATH_GL13:
+               case RENDERPATH_GLES1:
+#ifdef GL_ALPHA_TEST
                        // only fixed function uses alpha test, other paths use pixel kill capability in shaders
                        CHECKGLERROR
                        if (gl_state.alphatest)
@@ -2110,21 +2247,50 @@ void GL_AlphaTest(int state)
                        {
                                qglDisable(GL_ALPHA_TEST);CHECKGLERROR
                        }
-                       break;
-               case RENDERPATH_D3D9:
-#ifdef SUPPORTD3D
-//                     IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHATESTENABLE, gl_state.alphatest);
 #endif
                        break;
+               case RENDERPATH_D3D9:
                case RENDERPATH_D3D10:
-                       break;
                case RENDERPATH_D3D11:
+               case RENDERPATH_SOFT:
+               case RENDERPATH_GL20:
+               case RENDERPATH_GLES2:
                        break;
+               }
+       }
+}
+
+void GL_AlphaToCoverage(qboolean state)
+{
+       if (gl_state.alphatocoverage != state)
+       {
+               gl_state.alphatocoverage = state;
+               switch(vid.renderpath)
+               {
+               case RENDERPATH_GL11:
+               case RENDERPATH_GL13:
+               case RENDERPATH_GLES1:
+               case RENDERPATH_GLES2:
+               case RENDERPATH_D3D9:
+               case RENDERPATH_D3D10:
+               case RENDERPATH_D3D11:
                case RENDERPATH_SOFT:
-//                     DPSOFTRAST_AlphaTest(gl_state.alphatest);
                        break;
                case RENDERPATH_GL20:
-               case RENDERPATH_GLES2:
+#ifdef GL_SAMPLE_ALPHA_TO_COVERAGE_ARB
+                       // alpha to coverage turns the alpha value of the pixel into 0%, 25%, 50%, 75% or 100% by masking the multisample fragments accordingly
+                       CHECKGLERROR
+                       if (gl_state.alphatocoverage)
+                       {
+                               qglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);CHECKGLERROR
+//                             qglEnable(GL_MULTISAMPLE_ARB);CHECKGLERROR
+                       }
+                       else
+                       {
+                               qglDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);CHECKGLERROR
+//                             qglDisable(GL_MULTISAMPLE_ARB);CHECKGLERROR
+                       }
+#endif
                        break;
                }
        }
@@ -2142,6 +2308,7 @@ void GL_ColorMask(int r, int g, int b, int a)
                case RENDERPATH_GL11:
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
+               case RENDERPATH_GLES1:
                case RENDERPATH_GLES2:
                        CHECKGLERROR
                        qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
@@ -2176,6 +2343,7 @@ void GL_Color(float cr, float cg, float cb, float ca)
                {
                case RENDERPATH_GL11:
                case RENDERPATH_GL13:
+               case RENDERPATH_GLES1:
                        CHECKGLERROR
                        qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
                        CHECKGLERROR
@@ -2203,6 +2371,7 @@ void GL_Scissor (int x, int y, int width, int height)
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
+       case RENDERPATH_GLES1:
        case RENDERPATH_GLES2:
                CHECKGLERROR
                qglScissor(x, y,width,height);
@@ -2242,6 +2411,7 @@ void GL_ScissorTest(int state)
                case RENDERPATH_GL11:
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
+               case RENDERPATH_GLES1:
                case RENDERPATH_GLES2:
                        CHECKGLERROR
                        if(gl_state.scissortest)
@@ -2284,6 +2454,7 @@ void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilva
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
+       case RENDERPATH_GLES1:
        case RENDERPATH_GLES2:
                CHECKGLERROR
                if (mask & GL_COLOR_BUFFER_BIT)
@@ -2292,7 +2463,11 @@ void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilva
                }
                if (mask & GL_DEPTH_BUFFER_BIT)
                {
+#ifdef USE_GLES2
+                       qglClearDepthf(depthvalue);CHECKGLERROR
+#else
                        qglClearDepth(depthvalue);CHECKGLERROR
+#endif
                }
                if (mask & GL_STENCIL_BUFFER_BIT)
                {
@@ -2327,6 +2502,7 @@ void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpi
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
+       case RENDERPATH_GLES1:
        case RENDERPATH_GLES2:
                CHECKGLERROR
                qglReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR
@@ -2383,7 +2559,7 @@ void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpi
 void R_Mesh_Start(void)
 {
        BACKENDACTIVECHECK
-       R_Mesh_ResetRenderTargets();
+       R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
        R_Mesh_SetUseVBO();
        if (gl_printcheckerror.integer && !gl_paranoid.integer)
        {
@@ -2392,7 +2568,7 @@ void R_Mesh_Start(void)
        }
 }
 
-qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
+static qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
 {
        int shaderobject;
        int shadercompiled;
@@ -2404,7 +2580,7 @@ qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, cons
        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")))
+       if (compilelog[0] && (strstr(compilelog, "error") || strstr(compilelog, "ERROR") || strstr(compilelog, "Error") || strstr(compilelog, "WARNING") || strstr(compilelog, "warning") || strstr(compilelog, "Warning") || developer_extra.integer))
        {
                int i, j, pretextlines = 0;
                for (i = 0;i < numstrings - 1;i++)
@@ -2444,8 +2620,10 @@ unsigned int GL_Backend_CompileProgram(int vertexstrings_count, const char **ver
        qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD5, "Attrib_TexCoord5");
        qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD6, "Attrib_TexCoord6");
        qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD7, "Attrib_TexCoord7");
+#ifndef USE_GLES2
        if(vid.support.gl20shaders130)
                qglBindFragDataLocation(programobject, 0, "dp_FragColor");
+#endif
 
        if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER, "vertex", vertexstrings_count, vertexstrings_list))
                goto cleanup;
@@ -2463,7 +2641,7 @@ unsigned int GL_Backend_CompileProgram(int vertexstrings_count, const char **ver
        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"))
+               if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning") || developer_extra.integer)
                        Con_DPrintf("program link log:\n%s\n", linklog);
                // software vertex shader is ok but software fragment shader is WAY
                // too slow, fail program if so.
@@ -2489,18 +2667,6 @@ void GL_Backend_FreeProgram(unsigned int prog)
        CHECKGLERROR
 }
 
-void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
-{
-       int i;
-       if (offset)
-       {
-               for (i = 0;i < count;i++)
-                       *out++ = *in++ + offset;
-       }
-       else
-               memcpy(out, in, sizeof(*out) * count);
-}
-
 // renders triangles using vertices from the active arrays
 int paranoidblah = 0;
 void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const r_meshbuffer_t *element3i_indexbuffer, size_t element3i_bufferoffset, const unsigned short *element3s, const r_meshbuffer_t *element3s_indexbuffer, size_t element3s_bufferoffset)
@@ -2537,6 +2703,7 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
+       case RENDERPATH_GLES1:
        case RENDERPATH_GLES2:
                // check if the user specified to ignore static index buffers
                if (!gl_state.usevbo_staticindex || (gl_vbo.integer == 3 && !vid.forcevbo && (element3i_bufferoffset || element3s_bufferoffset)))
@@ -2658,137 +2825,221 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri
                        CHECKGLERROR
                        if (gl_mesh_testmanualfeeding.integer)
                        {
+#ifndef USE_GLES2
                                unsigned int i, j, element;
                                const GLfloat *p;
                                qglBegin(GL_TRIANGLES);
-                               for (i = 0;i < (unsigned int) numtriangles * 3;i++)
+                               if(vid.renderpath == RENDERPATH_GL20)
                                {
-                                       if (element3i)
-                                               element = element3i[i];
-                                       else if (element3s)
-                                               element = element3s[i];
-                                       else
-                                               element = firstvertex + i;
-                                       for (j = 0;j < vid.texarrayunits;j++)
+                                       for (i = 0;i < (unsigned int) numtriangles * 3;i++)
                                        {
-                                               if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled)
+                                               if (element3i)
+                                                       element = element3i[i];
+                                               else if (element3s)
+                                                       element = element3s[i];
+                                               else
+                                                       element = firstvertex + i;
+                                               for (j = 0;j < vid.texarrayunits;j++)
                                                {
-                                                       if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT)
+                                                       if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled)
                                                        {
-                                                               p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
-                                                               if (vid.texarrayunits > 1)
+                                                               if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT)
                                                                {
+                                                                       p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
                                                                        if (gl_state.units[j].pointer_texcoord_components == 4)
-                                                                               qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
+                                                                               qglVertexAttrib4f(GLSLATTRIB_TEXCOORD0 + j, p[0], p[1], p[2], p[3]);
                                                                        else if (gl_state.units[j].pointer_texcoord_components == 3)
-                                                                               qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
+                                                                               qglVertexAttrib3f(GLSLATTRIB_TEXCOORD0 + j, p[0], p[1], p[2]);
                                                                        else if (gl_state.units[j].pointer_texcoord_components == 2)
-                                                                               qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
+                                                                               qglVertexAttrib2f(GLSLATTRIB_TEXCOORD0 + j, p[0], p[1]);
                                                                        else
-                                                                               qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
+                                                                               qglVertexAttrib1f(GLSLATTRIB_TEXCOORD0 + j, p[0]);
                                                                }
-                                                               else
+                                                               else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT)
                                                                {
+                                                                       const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
                                                                        if (gl_state.units[j].pointer_texcoord_components == 4)
-                                                                               qglTexCoord4f(p[0], p[1], p[2], p[3]);
+                                                                               qglVertexAttrib4f(GLSLATTRIB_TEXCOORD0 + j, s[0], s[1], s[2], s[3]);
                                                                        else if (gl_state.units[j].pointer_texcoord_components == 3)
-                                                                               qglTexCoord3f(p[0], p[1], p[2]);
+                                                                               qglVertexAttrib3f(GLSLATTRIB_TEXCOORD0 + j, s[0], s[1], s[2]);
                                                                        else if (gl_state.units[j].pointer_texcoord_components == 2)
-                                                                               qglTexCoord2f(p[0], p[1]);
-                                                                       else
-                                                                               qglTexCoord1f(p[0]);
-                                                               }
-                                                       }
-                                                       else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT)
-                                                       {
-                                                               const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
-                                                               if (vid.texarrayunits > 1)
-                                                               {
-                                                                       if (gl_state.units[j].pointer_texcoord_components == 4)
-                                                                               qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2], s[3]);
-                                                                       else if (gl_state.units[j].pointer_texcoord_components == 3)
-                                                                               qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2]);
-                                                                       else if (gl_state.units[j].pointer_texcoord_components == 2)
-                                                                               qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, s[0], s[1]);
+                                                                               qglVertexAttrib2f(GLSLATTRIB_TEXCOORD0 + j, s[0], s[1]);
                                                                        else if (gl_state.units[j].pointer_texcoord_components == 1)
-                                                                               qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, s[0]);
+                                                                               qglVertexAttrib1f(GLSLATTRIB_TEXCOORD0 + j, s[0]);
                                                                }
-                                                               else
+                                                               else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE)
                                                                {
+                                                                       const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
                                                                        if (gl_state.units[j].pointer_texcoord_components == 4)
-                                                                               qglTexCoord4f(s[0], s[1], s[2], s[3]);
+                                                                               qglVertexAttrib4f(GLSLATTRIB_TEXCOORD0 + j, sb[0], sb[1], sb[2], sb[3]);
                                                                        else if (gl_state.units[j].pointer_texcoord_components == 3)
-                                                                               qglTexCoord3f(s[0], s[1], s[2]);
+                                                                               qglVertexAttrib3f(GLSLATTRIB_TEXCOORD0 + j, sb[0], sb[1], sb[2]);
                                                                        else if (gl_state.units[j].pointer_texcoord_components == 2)
-                                                                               qglTexCoord2f(s[0], s[1]);
+                                                                               qglVertexAttrib2f(GLSLATTRIB_TEXCOORD0 + j, sb[0], sb[1]);
                                                                        else if (gl_state.units[j].pointer_texcoord_components == 1)
-                                                                               qglTexCoord1f(s[0]);
+                                                                               qglVertexAttrib1f(GLSLATTRIB_TEXCOORD0 + j, sb[0]);
                                                                }
                                                        }
-                                                       else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE)
+                                               }
+                                               if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4)
+                                               {
+                                                       if (gl_state.pointer_color_gltype == GL_FLOAT)
+                                                       {
+                                                               p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
+                                                               qglVertexAttrib4f(GLSLATTRIB_COLOR, p[0], p[1], p[2], p[3]);
+                                                       }
+                                                       else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE)
+                                                       {
+                                                               const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
+                                                               qglVertexAttrib4Nub(GLSLATTRIB_COLOR, ub[0], ub[1], ub[2], ub[3]);
+                                                       }
+                                               }
+                                               if (gl_state.pointer_vertex_gltype == GL_FLOAT)
+                                               {
+                                                       p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride);
+                                                       if (gl_state.pointer_vertex_components == 4)
+                                                               qglVertexAttrib4f(GLSLATTRIB_POSITION, p[0], p[1], p[2], p[3]);
+                                                       else if (gl_state.pointer_vertex_components == 3)
+                                                               qglVertexAttrib3f(GLSLATTRIB_POSITION, p[0], p[1], p[2]);
+                                                       else
+                                                               qglVertexAttrib2f(GLSLATTRIB_POSITION, p[0], p[1]);
+                                               }
+                                       }
+                               }
+                               else
+                               {
+                                       for (i = 0;i < (unsigned int) numtriangles * 3;i++)
+                                       {
+                                               if (element3i)
+                                                       element = element3i[i];
+                                               else if (element3s)
+                                                       element = element3s[i];
+                                               else
+                                                       element = firstvertex + i;
+                                               for (j = 0;j < vid.texarrayunits;j++)
+                                               {
+                                                       if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled)
                                                        {
-                                                               const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
-                                                               if (vid.texarrayunits > 1)
+                                                               if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT)
                                                                {
-                                                                       if (gl_state.units[j].pointer_texcoord_components == 4)
-                                                                               qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2], sb[3]);
-                                                                       else if (gl_state.units[j].pointer_texcoord_components == 3)
-                                                                               qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2]);
-                                                                       else if (gl_state.units[j].pointer_texcoord_components == 2)
-                                                                               qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, sb[0], sb[1]);
-                                                                       else if (gl_state.units[j].pointer_texcoord_components == 1)
-                                                                               qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, sb[0]);
+                                                                       p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
+                                                                       if (vid.texarrayunits > 1)
+                                                                       {
+                                                                               if (gl_state.units[j].pointer_texcoord_components == 4)
+                                                                                       qglMultiTexCoord4f(GL_TEXTURE0 + j, p[0], p[1], p[2], p[3]);
+                                                                               else if (gl_state.units[j].pointer_texcoord_components == 3)
+                                                                                       qglMultiTexCoord3f(GL_TEXTURE0 + j, p[0], p[1], p[2]);
+                                                                               else if (gl_state.units[j].pointer_texcoord_components == 2)
+                                                                                       qglMultiTexCoord2f(GL_TEXTURE0 + j, p[0], p[1]);
+                                                                               else
+                                                                                       qglMultiTexCoord1f(GL_TEXTURE0 + j, p[0]);
+                                                                       }
+                                                                       else
+                                                                       {
+                                                                               if (gl_state.units[j].pointer_texcoord_components == 4)
+                                                                                       qglTexCoord4f(p[0], p[1], p[2], p[3]);
+                                                                               else if (gl_state.units[j].pointer_texcoord_components == 3)
+                                                                                       qglTexCoord3f(p[0], p[1], p[2]);
+                                                                               else if (gl_state.units[j].pointer_texcoord_components == 2)
+                                                                                       qglTexCoord2f(p[0], p[1]);
+                                                                               else
+                                                                                       qglTexCoord1f(p[0]);
+                                                                       }
                                                                }
-                                                               else
+                                                               else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT)
                                                                {
-                                                                       if (gl_state.units[j].pointer_texcoord_components == 4)
-                                                                               qglTexCoord4f(sb[0], sb[1], sb[2], sb[3]);
-                                                                       else if (gl_state.units[j].pointer_texcoord_components == 3)
-                                                                               qglTexCoord3f(sb[0], sb[1], sb[2]);
-                                                                       else if (gl_state.units[j].pointer_texcoord_components == 2)
-                                                                               qglTexCoord2f(sb[0], sb[1]);
-                                                                       else if (gl_state.units[j].pointer_texcoord_components == 1)
-                                                                               qglTexCoord1f(sb[0]);
+                                                                       const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
+                                                                       if (vid.texarrayunits > 1)
+                                                                       {
+                                                                               if (gl_state.units[j].pointer_texcoord_components == 4)
+                                                                                       qglMultiTexCoord4f(GL_TEXTURE0 + j, s[0], s[1], s[2], s[3]);
+                                                                               else if (gl_state.units[j].pointer_texcoord_components == 3)
+                                                                                       qglMultiTexCoord3f(GL_TEXTURE0 + j, s[0], s[1], s[2]);
+                                                                               else if (gl_state.units[j].pointer_texcoord_components == 2)
+                                                                                       qglMultiTexCoord2f(GL_TEXTURE0 + j, s[0], s[1]);
+                                                                               else if (gl_state.units[j].pointer_texcoord_components == 1)
+                                                                                       qglMultiTexCoord1f(GL_TEXTURE0 + j, s[0]);
+                                                                       }
+                                                                       else
+                                                                       {
+                                                                               if (gl_state.units[j].pointer_texcoord_components == 4)
+                                                                                       qglTexCoord4f(s[0], s[1], s[2], s[3]);
+                                                                               else if (gl_state.units[j].pointer_texcoord_components == 3)
+                                                                                       qglTexCoord3f(s[0], s[1], s[2]);
+                                                                               else if (gl_state.units[j].pointer_texcoord_components == 2)
+                                                                                       qglTexCoord2f(s[0], s[1]);
+                                                                               else if (gl_state.units[j].pointer_texcoord_components == 1)
+                                                                                       qglTexCoord1f(s[0]);
+                                                                       }
+                                                               }
+                                                               else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE)
+                                                               {
+                                                                       const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
+                                                                       if (vid.texarrayunits > 1)
+                                                                       {
+                                                                               if (gl_state.units[j].pointer_texcoord_components == 4)
+                                                                                       qglMultiTexCoord4f(GL_TEXTURE0 + j, sb[0], sb[1], sb[2], sb[3]);
+                                                                               else if (gl_state.units[j].pointer_texcoord_components == 3)
+                                                                                       qglMultiTexCoord3f(GL_TEXTURE0 + j, sb[0], sb[1], sb[2]);
+                                                                               else if (gl_state.units[j].pointer_texcoord_components == 2)
+                                                                                       qglMultiTexCoord2f(GL_TEXTURE0 + j, sb[0], sb[1]);
+                                                                               else if (gl_state.units[j].pointer_texcoord_components == 1)
+                                                                                       qglMultiTexCoord1f(GL_TEXTURE0 + j, sb[0]);
+                                                                       }
+                                                                       else
+                                                                       {
+                                                                               if (gl_state.units[j].pointer_texcoord_components == 4)
+                                                                                       qglTexCoord4f(sb[0], sb[1], sb[2], sb[3]);
+                                                                               else if (gl_state.units[j].pointer_texcoord_components == 3)
+                                                                                       qglTexCoord3f(sb[0], sb[1], sb[2]);
+                                                                               else if (gl_state.units[j].pointer_texcoord_components == 2)
+                                                                                       qglTexCoord2f(sb[0], sb[1]);
+                                                                               else if (gl_state.units[j].pointer_texcoord_components == 1)
+                                                                                       qglTexCoord1f(sb[0]);
+                                                                       }
                                                                }
                                                        }
                                                }
-                                       }
-                                       if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4)
-                                       {
-                                               if (gl_state.pointer_color_gltype == GL_FLOAT)
+                                               if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4)
                                                {
-                                                       p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
-                                                       qglColor4f(p[0], p[1], p[2], p[3]);
+                                                       if (gl_state.pointer_color_gltype == GL_FLOAT)
+                                                       {
+                                                               p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
+                                                               qglColor4f(p[0], p[1], p[2], p[3]);
+                                                       }
+                                                       else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE)
+                                                       {
+                                                               const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
+                                                               qglColor4ub(ub[0], ub[1], ub[2], ub[3]);
+                                                       }
                                                }
-                                               else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE)
+                                               if (gl_state.pointer_vertex_gltype == GL_FLOAT)
                                                {
-                                                       const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
-                                                       qglColor4ub(ub[0], ub[1], ub[2], ub[3]);
+                                                       p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride);
+                                                       if (gl_state.pointer_vertex_components == 4)
+                                                               qglVertex4f(p[0], p[1], p[2], p[3]);
+                                                       else if (gl_state.pointer_vertex_components == 3)
+                                                               qglVertex3f(p[0], p[1], p[2]);
+                                                       else
+                                                               qglVertex2f(p[0], p[1]);
                                                }
                                        }
-                                       if (gl_state.pointer_vertex_gltype == GL_FLOAT)
-                                       {
-                                               p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride);
-                                               if (gl_state.pointer_vertex_components == 4)
-                                                       qglVertex4f(p[0], p[1], p[2], p[3]);
-                                               else if (gl_state.pointer_vertex_components == 3)
-                                                       qglVertex3f(p[0], p[1], p[2]);
-                                               else
-                                                       qglVertex2f(p[0], p[1]);
-                                       }
                                }
                                qglEnd();
                                CHECKGLERROR
+#endif
                        }
                        else if (bufferobject3s)
                        {
                                GL_BindEBO(bufferobject3s);
+#ifndef USE_GLES2
                                if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
                                {
                                        qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s);
                                        CHECKGLERROR
                                }
                                else
+#endif
                                {
                                        qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)(firsttriangle * sizeof(unsigned short[3])));
                                        CHECKGLERROR
@@ -2797,12 +3048,14 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri
                        else if (bufferobject3i)
                        {
                                GL_BindEBO(bufferobject3i);
+#ifndef USE_GLES2
                                if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
                                {
                                        qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i);
                                        CHECKGLERROR
                                }
                                else
+#endif
                                {
                                        qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)(firsttriangle * sizeof(unsigned int[3])));
                                        CHECKGLERROR
@@ -2811,12 +3064,14 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri
                        else if (element3s)
                        {
                                GL_BindEBO(0);
+#ifndef USE_GLES2
                                if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
                                {
                                        qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, element3s);
                                        CHECKGLERROR
                                }
                                else
+#endif
                                {
                                        qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
                                        CHECKGLERROR
@@ -2825,12 +3080,14 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri
                        else if (element3i)
                        {
                                GL_BindEBO(0);
+#ifndef USE_GLES2
                                if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
                                {
                                        qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, element3i);
                                        CHECKGLERROR
                                }
                                else
+#endif
                                {
                                        qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
                                        CHECKGLERROR
@@ -2879,6 +3136,7 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri
                case RENDERPATH_SOFT:
                        DPSOFTRAST_DrawTriangles(firstvertex, numvertices, numtriangles, element3i, element3s);
                        break;
+               case RENDERPATH_GLES1:
                case RENDERPATH_GLES2:
                        // GLES does not have glDrawRangeElements, and generally
                        // underperforms with index buffers, so this code path is
@@ -2891,8 +3149,8 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri
                                GLint           attribsize;
                                GLenum          attribtype;
                                GLchar          attribname[1024];
-                               r = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
-                               if (r != GL_FRAMEBUFFER_COMPLETE_EXT)
+                               r = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
+                               if (r != GL_FRAMEBUFFER_COMPLETE)
                                        Con_DPrintf("fbo %i not complete (default %i)\n", gl_state.framebufferobject, gl_state.defaultframebufferobject);
 #ifndef GL_CURRENT_PROGRAM
 #define GL_CURRENT_PROGRAM 0x8B8D
@@ -2934,7 +3192,7 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri
 // restores backend state, used when done with 3D rendering
 void R_Mesh_Finish(void)
 {
-       R_Mesh_ResetRenderTargets();
+       R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
 }
 
 r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isdynamic, qboolean isindex16)
@@ -2974,6 +3232,7 @@ void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t si
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
+       case RENDERPATH_GLES1:
        case RENDERPATH_GLES2:
                if (!buffer->bufferobject)
                        qglGenBuffersARB(1, (GLuint *)&buffer->bufferobject);
@@ -2981,7 +3240,7 @@ void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t si
                        GL_BindEBO(buffer->bufferobject);
                else
                        GL_BindVBO(buffer->bufferobject);
-               qglBufferDataARB(buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB, size, data, buffer->isdynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB);
+               qglBufferDataARB(buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER, size, data, buffer->isdynamic ? GL_STREAM_DRAW : GL_STATIC_DRAW);
                break;
        case RENDERPATH_D3D9:
 #ifdef SUPPORTD3D
@@ -3055,6 +3314,7 @@ void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
+       case RENDERPATH_GLES1:
        case RENDERPATH_GLES2:
                qglDeleteBuffersARB(1, (GLuint *)&buffer->bufferobject);
                break;
@@ -3110,6 +3370,7 @@ void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void
        {
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
                if (gl_state.pointer_vertex_components != components || gl_state.pointer_vertex_gltype != gltype || gl_state.pointer_vertex_stride != stride || gl_state.pointer_vertex_pointer != pointer || gl_state.pointer_vertex_vertexbuffer != vertexbuffer || gl_state.pointer_vertex_offset != bufferoffset)
                {
                        int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
@@ -3156,6 +3417,8 @@ void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *
        {
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
+#ifdef GL_MODELVIEW
                CHECKGLERROR
                if (pointer)
                {
@@ -3192,6 +3455,7 @@ void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *
                                qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
                        }
                }
+#endif
                break;
        case RENDERPATH_GL20:
        case RENDERPATH_GLES2:
@@ -3250,6 +3514,8 @@ void R_Mesh_TexCoordPointer(unsigned int unitnum, int components, int gltype, si
        {
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
+#ifdef GL_MODELVIEW
                CHECKGLERROR
                if (pointer)
                {
@@ -3285,6 +3551,7 @@ void R_Mesh_TexCoordPointer(unsigned int unitnum, int components, int gltype, si
                                qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
                        }
                }
+#endif
                break;
        case RENDERPATH_GL20:
        case RENDERPATH_GLES2:
@@ -3338,7 +3605,7 @@ int R_Mesh_TexBound(unsigned int unitnum, int id)
                return unit->t2d;
        if (id == GL_TEXTURE_3D)
                return unit->t3d;
-       if (id == GL_TEXTURE_CUBE_MAP_ARB)
+       if (id == GL_TEXTURE_CUBE_MAP)
                return unit->tcubemap;
        return 0;
 }
@@ -3350,6 +3617,7 @@ void R_Mesh_CopyToTexture(rtexture_t *tex, int tx, int ty, int sx, int sy, int w
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
+       case RENDERPATH_GLES1:
        case RENDERPATH_GLES2:
                R_Mesh_TexBind(0, tex);
                GL_ActiveTexture(0);CHECKGLERROR
@@ -3440,11 +3708,12 @@ void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
                {
                case GL_TEXTURE_2D: if (unit->t2d != texnum) {GL_ActiveTexture(unitnum);unit->t2d = texnum;qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR}break;
                case GL_TEXTURE_3D: if (unit->t3d != texnum) {GL_ActiveTexture(unitnum);unit->t3d = texnum;qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR}break;
-               case GL_TEXTURE_CUBE_MAP_ARB: if (unit->tcubemap != texnum) {GL_ActiveTexture(unitnum);unit->tcubemap = texnum;qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR}break;
+               case GL_TEXTURE_CUBE_MAP: if (unit->tcubemap != texnum) {GL_ActiveTexture(unitnum);unit->tcubemap = texnum;qglBindTexture(GL_TEXTURE_CUBE_MAP, unit->tcubemap);CHECKGLERROR}break;
                }
                break;
-       case RENDERPATH_GL13:
        case RENDERPATH_GL11:
+       case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
                unit->texture = tex;
                tex2d = 0;
                tex3d = 0;
@@ -3460,7 +3729,7 @@ void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
                        case GL_TEXTURE_3D:
                                tex3d = texnum;
                                break;
-                       case GL_TEXTURE_CUBE_MAP_ARB:
+                       case GL_TEXTURE_CUBE_MAP:
                                texcubemap = texnum;
                                break;
                        }
@@ -3515,18 +3784,18 @@ void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
                        {
                                if (unit->tcubemap == 0)
                                {
-                                       qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
+                                       qglEnable(GL_TEXTURE_CUBE_MAP);CHECKGLERROR
                                }
                        }
                        else
                        {
                                if (unit->tcubemap)
                                {
-                                       qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
+                                       qglDisable(GL_TEXTURE_CUBE_MAP);CHECKGLERROR
                                }
                        }
                        unit->tcubemap = texcubemap;
-                       qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
+                       qglBindTexture(GL_TEXTURE_CUBE_MAP, unit->tcubemap);CHECKGLERROR
                }
                break;
        case RENDERPATH_D3D9:
@@ -3591,7 +3860,9 @@ void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
+       case RENDERPATH_GLES1:
        case RENDERPATH_GLES2:
+#ifdef GL_MODELVIEW
                if (matrix && matrix->m[3][3])
                {
                        // texmatrix specified, check if it is different
@@ -3622,6 +3893,7 @@ void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
                                qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
                        }
                }
+#endif
                break;
        case RENDERPATH_D3D9:
        case RENDERPATH_D3D10:
@@ -3643,6 +3915,8 @@ void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, i
                // do nothing
                break;
        case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
+#ifdef GL_TEXTURE_ENV
                // GL_ARB_texture_env_combine
                if (!combinergb)
                        combinergb = GL_MODULATE;
@@ -3655,31 +3929,31 @@ void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, i
                if (combinergb != combinealpha || rgbscale != 1 || alphascale != 1)
                {
                        if (combinergb == GL_DECAL)
-                               combinergb = GL_INTERPOLATE_ARB;
-                       if (unit->combine != GL_COMBINE_ARB)
+                               combinergb = GL_INTERPOLATE;
+                       if (unit->combine != GL_COMBINE)
                        {
-                               unit->combine = GL_COMBINE_ARB;
+                               unit->combine = GL_COMBINE;
                                GL_ActiveTexture(unitnum);
-                               qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
-                               qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE_ARB mode
+                               qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);CHECKGLERROR
+                               qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE mode
                        }
                        if (unit->combinergb != combinergb)
                        {
                                unit->combinergb = combinergb;
                                GL_ActiveTexture(unitnum);
-                               qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
+                               qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, unit->combinergb);CHECKGLERROR
                        }
                        if (unit->combinealpha != combinealpha)
                        {
                                unit->combinealpha = combinealpha;
                                GL_ActiveTexture(unitnum);
-                               qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
+                               qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, unit->combinealpha);CHECKGLERROR
                        }
                        if (unit->rgbscale != rgbscale)
                        {
                                unit->rgbscale = rgbscale;
                                GL_ActiveTexture(unitnum);
-                               qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, unit->rgbscale);CHECKGLERROR
+                               qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, unit->rgbscale);CHECKGLERROR
                        }
                        if (unit->alphascale != alphascale)
                        {
@@ -3697,9 +3971,11 @@ void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, i
                                qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
                        }
                }
+#endif
                break;
        case RENDERPATH_GL11:
                // normal GL texenv
+#ifdef GL_TEXTURE_ENV
                if (!combinergb)
                        combinergb = GL_MODULATE;
                if (unit->combine != combinergb)
@@ -3708,6 +3984,7 @@ void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, i
                        GL_ActiveTexture(unitnum);
                        qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
                }
+#endif
                break;
        case RENDERPATH_D3D9:
        case RENDERPATH_D3D10:
@@ -3737,8 +4014,9 @@ void R_Mesh_ResetTextureState(void)
        case RENDERPATH_D3D11:
        case RENDERPATH_SOFT:
                break;
-       case RENDERPATH_GL13:
        case RENDERPATH_GL11:
+       case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
                for (unitnum = 0;unitnum < vid.texunits;unitnum++)
                {
                        R_Mesh_TexCombine(unitnum, GL_MODULATE, GL_MODULATE, 1, 1);
@@ -3797,6 +4075,7 @@ static void R_Mesh_InitVertexDeclarations(void)
        case RENDERPATH_GL20:
        case RENDERPATH_GL13:
        case RENDERPATH_GL11:
+       case RENDERPATH_GLES1:
        case RENDERPATH_GLES2:
                break;
        case RENDERPATH_D3D9:
@@ -3870,6 +4149,7 @@ void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, con
                }
                break;
        case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
                if (vertexbuffer)
                {
                        R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
@@ -3973,8 +4253,9 @@ void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3
                        return;
                }
                break;
-       case RENDERPATH_GL13:
        case RENDERPATH_GL11:
+       case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
                if (!vid.useinterleavedarrays)
                {
                        R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
@@ -4062,6 +4343,7 @@ void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *ve
                }
                break;
        case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
                if (vertexbuffer)
                {
                        R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
@@ -4165,8 +4447,9 @@ void R_Mesh_PrepareVertices_Mesh_Arrays(int numvertices, const float *vertex3f,
                        return;
                }
                break;
-       case RENDERPATH_GL13:
        case RENDERPATH_GL11:
+       case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
                if (!vid.useinterleavedarrays)
                {
                        R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
@@ -4265,6 +4548,7 @@ void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex,
                }
                break;
        case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
                if (vertexbuffer)
                {
                        R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
@@ -4323,3 +4607,61 @@ void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex,
                break;
        }
 }
+
+void GL_BlendEquationSubtract(qboolean negated)
+{
+       if(negated)
+       {
+               switch(vid.renderpath)
+               {
+               case RENDERPATH_GL11:
+               case RENDERPATH_GL13:
+               case RENDERPATH_GL20:
+               case RENDERPATH_GLES1:
+               case RENDERPATH_GLES2:
+                       qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT);
+                       break;
+               case RENDERPATH_D3D9:
+#ifdef SUPPORTD3D
+                       IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_BLENDOP, D3DBLENDOP_SUBTRACT);
+#endif
+                       break;
+               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;
+               case RENDERPATH_SOFT:
+                       DPSOFTRAST_BlendSubtract(true);
+                       break;
+               }
+       }
+       else
+       {
+               switch(vid.renderpath)
+               {
+               case RENDERPATH_GL11:
+               case RENDERPATH_GL13:
+               case RENDERPATH_GL20:
+               case RENDERPATH_GLES1:
+               case RENDERPATH_GLES2:
+                       qglBlendEquationEXT(GL_FUNC_ADD);
+                       break;
+               case RENDERPATH_D3D9:
+#ifdef SUPPORTD3D
+                       IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_BLENDOP, D3DBLENDOP_ADD);
+#endif
+                       break;
+               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;
+               case RENDERPATH_SOFT:
+                       DPSOFTRAST_BlendSubtract(false);
+                       break;
+               }
+       }
+}