added RENDERPATH_GLES2
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 7 Feb 2011 03:32:23 +0000 (03:32 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 7 Feb 2011 03:32:23 +0000 (03:32 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@10818 d7cf8633-e32d-0410-b094-e92efae38249

dpsoftrast.h
gl_backend.c
gl_draw.c
gl_rmain.c
gl_textures.c
model_brush.c
r_shadow.c
vid.h
vid_sdl.c
vid_shared.c

index 67e463d..c91eee0 100644 (file)
@@ -123,6 +123,21 @@ typedef enum gl20_texunit_e
 }
 gl20_texunit;
 
+typedef enum gles2_attrib_e
+{
+       GLES2ATTRIB_POSITION = 0,
+       GLES2ATTRIB_COLOR = 1,
+       GLES2ATTRIB_TEXCOORD0 = 2,
+       GLES2ATTRIB_TEXCOORD1 = 3,
+       GLES2ATTRIB_TEXCOORD2 = 4,
+       GLES2ATTRIB_TEXCOORD3 = 5,
+       GLES2ATTRIB_TEXCOORD4 = 6,
+       GLES2ATTRIB_TEXCOORD5 = 7,
+       GLES2ATTRIB_TEXCOORD6 = 8,
+       GLES2ATTRIB_TEXCOORD7 = 9,
+}
+gles2_attrib;
+
 // this enum selects which of the glslshadermodeinfo entries should be used
 typedef enum shadermode_e
 {
index 494e657..b450a84 100644 (file)
@@ -147,6 +147,7 @@ typedef struct gl_state_s
        int vertexbufferobject;
        int elementbufferobject;
        int framebufferobject;
+       int defaultframebufferobject; // RENDERPATH_GLES2 has a non-zero fbo provided by the OS
        qboolean pointer_color_enabled;
 
        int pointer_vertex_components;
@@ -296,6 +297,12 @@ static void R_Mesh_SetUseVBO(void)
                gl_state.usevbo_dynamicvertex = false;
                gl_state.usevbo_dynamicindex = false;
                break;
+       case RENDERPATH_GLES2:
+               gl_state.usevbo_staticvertex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
+               gl_state.usevbo_staticindex = false;
+               gl_state.usevbo_dynamicvertex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer) || vid.forcevbo;
+               gl_state.usevbo_dynamicindex = false;
+               break;
        }
 }
 
@@ -320,6 +327,10 @@ static void gl_backend_start(void)
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       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);
                break;
        case RENDERPATH_D3D9:
 #ifdef SUPPORTD3D
@@ -348,6 +359,8 @@ static void gl_backend_shutdown(void)
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
                break;
        case RENDERPATH_D3D9:
 #ifdef SUPPORTD3D
@@ -361,8 +374,6 @@ static void gl_backend_shutdown(void)
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
-       case RENDERPATH_SOFT:
-               break;
        }
 
        if (gl_state.preparevertices_tempdata)
@@ -394,6 +405,8 @@ static void gl_backend_devicelost(void)
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
                break;
        case RENDERPATH_D3D9:
 #ifdef SUPPORTD3D
@@ -407,8 +420,6 @@ static void gl_backend_devicelost(void)
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
-       case RENDERPATH_SOFT:
-               break;
        }
        endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
        for (i = 0;i < endindex;i++)
@@ -422,6 +433,8 @@ static void gl_backend_devicelost(void)
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
                case RENDERPATH_CGGL:
+               case RENDERPATH_SOFT:
+               case RENDERPATH_GLES2:
                        break;
                case RENDERPATH_D3D9:
 #ifdef SUPPORTD3D
@@ -441,8 +454,6 @@ static void gl_backend_devicelost(void)
                case RENDERPATH_D3D11:
                        Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                        break;
-               case RENDERPATH_SOFT:
-                       break;
                }
        }
 }
@@ -455,6 +466,8 @@ static void gl_backend_devicerestored(void)
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
                break;
        case RENDERPATH_D3D9:
 #ifdef SUPPORTD3D
@@ -468,8 +481,6 @@ static void gl_backend_devicerestored(void)
        case RENDERPATH_D3D11:
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
-       case RENDERPATH_SOFT:
-               break;
        }
 }
 
@@ -682,6 +693,7 @@ qboolean R_ScissorForBBox(const float *mins, const float *maxs, int *scissor)
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
                break;
        }
 
@@ -765,6 +777,7 @@ void R_Viewport_InitOrtho(r_viewport_t *v, const matrix4x4_t *cameramatrix, int
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
                break;
        case RENDERPATH_D3D9:
        case RENDERPATH_D3D10:
@@ -1015,6 +1028,7 @@ void R_Viewport_InitRectSideView(r_viewport_t *v, const matrix4x4_t *cameramatri
        case RENDERPATH_GL13:
        case RENDERPATH_GL11:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
                break;
        case RENDERPATH_D3D9:
                m[5] *= -1;
@@ -1085,6 +1099,10 @@ void R_SetViewport(const r_viewport_t *v)
        case RENDERPATH_SOFT:
                DPSOFTRAST_Viewport(v->x, v->y, v->width, v->height);
                break;
+       case RENDERPATH_GLES2:
+               CHECKGLERROR
+               qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
+               break;
        }
 
        // force an update of the derived matrices
@@ -1126,6 +1144,7 @@ int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colorte
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                if (!vid.support.ext_framebuffer_object)
                        return 0;
                qglGenFramebuffersEXT(1, (GLuint*)&temp);CHECKGLERROR
@@ -1154,6 +1173,7 @@ void R_Mesh_DestroyFramebufferObject(int fbo)
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                if (fbo)
                        qglDeleteFramebuffersEXT(1, (GLuint*)&fbo);
                break;
@@ -1210,10 +1230,11 @@ void R_Mesh_ResetRenderTargets(void)
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                if (gl_state.framebufferobject)
                {
                        gl_state.framebufferobject = 0;
-                       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject);
+                       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.defaultframebufferobject);
                }
                break;
        case RENDERPATH_D3D9:
@@ -1253,10 +1274,11 @@ void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colo
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                if (gl_state.framebufferobject != fbo)
                {
                        gl_state.framebufferobject = fbo;
-                       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject);
+                       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject ? gl_state.framebufferobject : gl_state.defaultframebufferobject);
                }
                break;
        case RENDERPATH_D3D9:
@@ -1524,6 +1546,49 @@ static void GL_Backend_ResetState(void)
                DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
                DPSOFTRAST_Viewport(0, 0, vid.width, vid.height);
                break;
+       case RENDERPATH_GLES2:
+               CHECKGLERROR
+               qglColorMask(1, 1, 1, 1);CHECKGLERROR
+               qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
+               qglDisable(GL_BLEND);CHECKGLERROR
+               qglCullFace(gl_state.cullface);CHECKGLERROR
+               qglDisable(GL_CULL_FACE);CHECKGLERROR
+               qglDepthFunc(GL_LEQUAL);CHECKGLERROR
+               qglEnable(GL_DEPTH_TEST);CHECKGLERROR
+               qglDepthMask(gl_state.depthmask);CHECKGLERROR
+               qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
+               qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+               qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+               qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+               qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.defaultframebufferobject);
+               qglEnableVertexAttribArray(GLES2ATTRIB_POSITION);
+               qglVertexAttribPointer(GLES2ATTRIB_POSITION, 3, GL_FLOAT, false, sizeof(float[3]), NULL);CHECKGLERROR
+               qglDisableVertexAttribArray(GLES2ATTRIB_COLOR);
+               qglVertexAttribPointer(GLES2ATTRIB_COLOR, 4, GL_FLOAT, false, sizeof(float[4]), NULL);CHECKGLERROR
+               qglVertexAttrib4f(GLES2ATTRIB_COLOR, 1, 1, 1, 1);
+               gl_state.unit = MAX_TEXTUREUNITS;
+               gl_state.clientunit = MAX_TEXTUREUNITS;
+               for (i = 0;i < vid.teximageunits;i++)
+               {
+                       GL_ActiveTexture(i);
+                       qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
+                       if (vid.support.ext_texture_3d)
+                       {
+                               qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
+                       }
+                       if (vid.support.arb_texture_cube_map)
+                       {
+                               qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
+                       }
+               }
+               for (i = 0;i < vid.texarrayunits;i++)
+               {
+                       GL_BindVBO(0);
+                       qglVertexAttribPointer(i+GLES2ATTRIB_TEXCOORD0, 2, GL_FLOAT, false, sizeof(float[2]), NULL);CHECKGLERROR
+                       qglDisableVertexAttribArray(i+GLES2ATTRIB_TEXCOORD0);CHECKGLERROR
+               }
+               CHECKGLERROR
+               break;
        }
 }
 
@@ -1538,6 +1603,7 @@ void GL_ActiveTexture(unsigned int num)
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
                case RENDERPATH_CGGL:
+               case RENDERPATH_GLES2:
                        if (qglActiveTexture)
                        {
                                CHECKGLERROR
@@ -1579,6 +1645,8 @@ void GL_ClientActiveTexture(unsigned int num)
                        break;
                case RENDERPATH_SOFT:
                        break;
+               case RENDERPATH_GLES2:
+                       break;
                }
        }
 }
@@ -1597,6 +1665,7 @@ void GL_BlendFunc(int blendfunc1, int blendfunc2)
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
                case RENDERPATH_CGGL:
+               case RENDERPATH_GLES2:
                        CHECKGLERROR
                        qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
                        if (gl_state.blend != blendenable)
@@ -1670,6 +1739,7 @@ void GL_DepthMask(int state)
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
                case RENDERPATH_CGGL:
+               case RENDERPATH_GLES2:
                        CHECKGLERROR
                        qglDepthMask(gl_state.depthmask);CHECKGLERROR
                        break;
@@ -1702,6 +1772,7 @@ void GL_DepthTest(int state)
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
                case RENDERPATH_CGGL:
+               case RENDERPATH_GLES2:
                        CHECKGLERROR
                        if (gl_state.depthtest)
                        {
@@ -1741,6 +1812,7 @@ void GL_DepthFunc(int state)
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
                case RENDERPATH_CGGL:
+               case RENDERPATH_GLES2:
                        CHECKGLERROR
                        qglDepthFunc(gl_state.depthfunc);CHECKGLERROR
                        break;
@@ -1799,6 +1871,11 @@ void GL_DepthRange(float nearfrac, float farfrac)
                case RENDERPATH_SOFT:
                        DPSOFTRAST_DepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
                        break;
+               case RENDERPATH_GLES2:
+                       //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+                       // FIXME: qglDepthRangef instead...  faster...
+                       qglDepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
+                       break;
                }
        }
 }
@@ -1866,6 +1943,9 @@ void R_SetStencilSeparate(qboolean enable, int writemask, int frontfail, int fro
        case RENDERPATH_SOFT:
                //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_GLES2:
+               //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+               break;
        }
 }
 
@@ -1877,6 +1957,7 @@ void R_SetStencil(qboolean enable, int writemask, int fail, int zfail, int zpass
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                CHECKGLERROR
                if (enable)
                {
@@ -1933,6 +2014,7 @@ void GL_PolygonOffset(float planeoffset, float depthoffset)
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
                case RENDERPATH_CGGL:
+               case RENDERPATH_GLES2:
                        qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
                        break;
                case RENDERPATH_D3D9:
@@ -1971,6 +2053,7 @@ void GL_SetMirrorState(qboolean state)
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
                case RENDERPATH_CGGL:
+               case RENDERPATH_GLES2:
                        qglCullFace(gl_state.cullface);
                        break;
                case RENDERPATH_D3D9:
@@ -2007,6 +2090,7 @@ void GL_CullFace(int state)
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                CHECKGLERROR
 
                if (state != GL_NONE)
@@ -2106,6 +2190,8 @@ void GL_AlphaTest(int state)
                case RENDERPATH_SOFT:
                        DPSOFTRAST_AlphaTest(gl_state.alphatest);
                        break;
+               case RENDERPATH_GLES2:
+                       break;
                }
        }
 }
@@ -2140,6 +2226,8 @@ void GL_AlphaFunc(int state, float value)
                case RENDERPATH_SOFT:
                        DPSOFTRAST_AlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);
                        break;
+               case RENDERPATH_GLES2:
+                       break;
                }
        }
 }
@@ -2157,6 +2245,7 @@ void GL_ColorMask(int r, int g, int b, int a)
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
                case RENDERPATH_CGGL:
+               case RENDERPATH_GLES2:
                        CHECKGLERROR
                        qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
                        break;
@@ -2204,6 +2293,9 @@ void GL_Color(float cr, float cg, float cb, float ca)
                case RENDERPATH_SOFT:
                        DPSOFTRAST_Color4f(cr, cg, cb, ca);
                        break;
+               case RENDERPATH_GLES2:
+                       qglVertexAttrib4f(GLES2ATTRIB_COLOR, cr, cg, cb, ca);
+                       break;
                }
        }
 }
@@ -2216,6 +2308,7 @@ void GL_Scissor (int x, int y, int width, int height)
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                CHECKGLERROR
                qglScissor(x, y,width,height);
                CHECKGLERROR
@@ -2255,6 +2348,7 @@ void GL_ScissorTest(int state)
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
                case RENDERPATH_CGGL:
+               case RENDERPATH_GLES2:
                        CHECKGLERROR
                        if(gl_state.scissortest)
                                qglEnable(GL_SCISSOR_TEST);
@@ -2297,6 +2391,7 @@ void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilva
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                CHECKGLERROR
                if (mask & GL_COLOR_BUFFER_BIT)
                {
@@ -2340,6 +2435,7 @@ void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpi
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                CHECKGLERROR
                qglReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR
                break;
@@ -2537,6 +2633,7 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       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)))
                {
@@ -2879,6 +2976,26 @@ 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_GLES2:
+                       // GLES does not have glDrawRangeElements, and generally
+                       // underperforms with index buffers, so this code path is
+                       // relatively straightforward...
+                       if (element3s)
+                       {
+                               qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
+                               CHECKGLERROR
+                       }
+                       else if (element3i)
+                       {
+                               qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
+                               CHECKGLERROR
+                       }
+                       else
+                       {
+                               qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
+                               CHECKGLERROR
+                       }
+                       break;
                }
        }
 }
@@ -2927,6 +3044,7 @@ void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t si
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                if (!buffer->bufferobject)
                        qglGenBuffersARB(1, (GLuint *)&buffer->bufferobject);
                if (buffer->isindexbuffer)
@@ -3008,6 +3126,7 @@ void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                qglDeleteBuffersARB(1, (GLuint *)&buffer->bufferobject);
                break;
        case RENDERPATH_D3D9:
@@ -3058,18 +3177,46 @@ void GL_Mesh_ListVBOs(qboolean printeach)
 
 void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
 {
-       int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
-       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)
+       switch(vid.renderpath)
        {
-               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;
-               CHECKGLERROR
-               GL_BindVBO(bufferobject);
-               qglVertexPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
+       case RENDERPATH_GL11:
+       case RENDERPATH_GL13:
+       case RENDERPATH_GL20:
+       case RENDERPATH_CGGL:
+               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;
+                       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;
+                       CHECKGLERROR
+                       GL_BindVBO(bufferobject);
+                       qglVertexPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
+               }
+               break;
+       case RENDERPATH_GLES2:
+               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;
+                       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;
+                       CHECKGLERROR
+                       GL_BindVBO(bufferobject);
+                       qglVertexAttribPointer(GLES2ATTRIB_POSITION, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
+               }
+               break;
+       case RENDERPATH_D3D9:
+       case RENDERPATH_D3D10:
+       case RENDERPATH_D3D11:
+       case RENDERPATH_SOFT:
+               break;
        }
 }
 
@@ -3077,40 +3224,92 @@ void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *
 {
        // note: vertexbuffer may be non-NULL even if pointer is NULL, so check
        // the pointer only.
-       if (pointer)
+       switch(vid.renderpath)
        {
-               int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
-               // caller wants color array enabled
-               if (!gl_state.pointer_color_enabled)
+       case RENDERPATH_GL11:
+       case RENDERPATH_GL13:
+       case RENDERPATH_GL20:
+       case RENDERPATH_CGGL:
+               CHECKGLERROR
+               if (pointer)
                {
-                       gl_state.pointer_color_enabled = true;
-                       CHECKGLERROR
-                       qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
+                       // caller wants color array enabled
+                       int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
+                       if (!gl_state.pointer_color_enabled)
+                       {
+                               gl_state.pointer_color_enabled = true;
+                               CHECKGLERROR
+                               qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
+                       }
+                       if (gl_state.pointer_color_components != components || gl_state.pointer_color_gltype != gltype || gl_state.pointer_color_stride != stride || gl_state.pointer_color_pointer != pointer || gl_state.pointer_color_vertexbuffer != vertexbuffer || gl_state.pointer_color_offset != bufferoffset)
+                       {
+                               gl_state.pointer_color_components = components;
+                               gl_state.pointer_color_gltype = gltype;
+                               gl_state.pointer_color_stride = stride;
+                               gl_state.pointer_color_pointer = pointer;
+                               gl_state.pointer_color_vertexbuffer = vertexbuffer;
+                               gl_state.pointer_color_offset = bufferoffset;
+                               CHECKGLERROR
+                               GL_BindVBO(bufferobject);
+                               qglColorPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
+                       }
                }
-               if (gl_state.pointer_color_components != components || gl_state.pointer_color_gltype != gltype || gl_state.pointer_color_stride != stride || gl_state.pointer_color_pointer != pointer || gl_state.pointer_color_vertexbuffer != vertexbuffer || gl_state.pointer_color_offset != bufferoffset)
+               else
                {
-                       gl_state.pointer_color_components = components;
-                       gl_state.pointer_color_gltype = gltype;
-                       gl_state.pointer_color_stride = stride;
-                       gl_state.pointer_color_pointer = pointer;
-                       gl_state.pointer_color_vertexbuffer = vertexbuffer;
-                       gl_state.pointer_color_offset = bufferoffset;
-                       CHECKGLERROR
-                       GL_BindVBO(bufferobject);
-                       qglColorPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
+                       // caller wants color array disabled
+                       if (gl_state.pointer_color_enabled)
+                       {
+                               gl_state.pointer_color_enabled = false;
+                               CHECKGLERROR
+                               qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
+                               // when color array is on the glColor gets trashed, set it again
+                               qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
+                       }
                }
-       }
-       else
-       {
-               // caller wants color array disabled
-               if (gl_state.pointer_color_enabled)
+               break;
+       case RENDERPATH_GLES2:
+               CHECKGLERROR
+               if (pointer)
                {
-                       gl_state.pointer_color_enabled = false;
-                       CHECKGLERROR
-                       qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
-                       // when color array is on the glColor gets trashed, set it again
-                       qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
+                       // caller wants color array enabled
+                       int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
+                       if (!gl_state.pointer_color_enabled)
+                       {
+                               gl_state.pointer_color_enabled = true;
+                               CHECKGLERROR
+                               qglEnableVertexAttribArray(GLES2ATTRIB_COLOR);CHECKGLERROR
+                       }
+                       if (gl_state.pointer_color_components != components || gl_state.pointer_color_gltype != gltype || gl_state.pointer_color_stride != stride || gl_state.pointer_color_pointer != pointer || gl_state.pointer_color_vertexbuffer != vertexbuffer || gl_state.pointer_color_offset != bufferoffset)
+                       {
+                               gl_state.pointer_color_components = components;
+                               gl_state.pointer_color_gltype = gltype;
+                               gl_state.pointer_color_stride = stride;
+                               gl_state.pointer_color_pointer = pointer;
+                               gl_state.pointer_color_vertexbuffer = vertexbuffer;
+                               gl_state.pointer_color_offset = bufferoffset;
+                               CHECKGLERROR
+                               GL_BindVBO(bufferobject);
+                               qglVertexAttribPointer(GLES2ATTRIB_COLOR, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
+                       }
                }
+               else
+               {
+                       // caller wants color array disabled
+                       if (gl_state.pointer_color_enabled)
+                       {
+                               gl_state.pointer_color_enabled = false;
+                               CHECKGLERROR
+                               qglDisableVertexAttribArray(GLES2ATTRIB_COLOR);CHECKGLERROR
+                               // when color array is on the glColor gets trashed, set it again
+                               qglVertexAttrib4f(GLES2ATTRIB_COLOR, gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
+                       }
+               }
+               break;
+       case RENDERPATH_D3D9:
+       case RENDERPATH_D3D10:
+       case RENDERPATH_D3D11:
+       case RENDERPATH_SOFT:
+               break;
        }
 }
 
@@ -3118,42 +3317,89 @@ void R_Mesh_TexCoordPointer(unsigned int unitnum, int components, int gltype, si
 {
        gltextureunit_t *unit = gl_state.units + unitnum;
        // update array settings
-       CHECKGLERROR
        // note: there is no need to check bufferobject here because all cases
        // that involve a valid bufferobject also supply a texcoord array
-       if (pointer)
+       switch(vid.renderpath)
        {
-               int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
-               // texture array unit is enabled, enable the array
-               if (!unit->arrayenabled)
+       case RENDERPATH_GL11:
+       case RENDERPATH_GL13:
+       case RENDERPATH_GL20:
+       case RENDERPATH_CGGL:
+               CHECKGLERROR
+               if (pointer)
                {
-                       unit->arrayenabled = true;
-                       GL_ClientActiveTexture(unitnum);
-                       qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
+                       int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
+                       // texture array unit is enabled, enable the array
+                       if (!unit->arrayenabled)
+                       {
+                               unit->arrayenabled = true;
+                               GL_ClientActiveTexture(unitnum);
+                               qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
+                       }
+                       // texcoord array
+                       if (unit->pointer_texcoord_components != components || unit->pointer_texcoord_gltype != gltype || unit->pointer_texcoord_stride != stride || unit->pointer_texcoord_pointer != pointer || unit->pointer_texcoord_vertexbuffer != vertexbuffer || unit->pointer_texcoord_offset != bufferoffset)
+                       {
+                               unit->pointer_texcoord_components = components;
+                               unit->pointer_texcoord_gltype = gltype;
+                               unit->pointer_texcoord_stride = stride;
+                               unit->pointer_texcoord_pointer = pointer;
+                               unit->pointer_texcoord_vertexbuffer = vertexbuffer;
+                               unit->pointer_texcoord_offset = bufferoffset;
+                               GL_ClientActiveTexture(unitnum);
+                               GL_BindVBO(bufferobject);
+                               qglTexCoordPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
+                       }
                }
-               // texcoord array
-               if (unit->pointer_texcoord_components != components || unit->pointer_texcoord_gltype != gltype || unit->pointer_texcoord_stride != stride || unit->pointer_texcoord_pointer != pointer || unit->pointer_texcoord_vertexbuffer != vertexbuffer || unit->pointer_texcoord_offset != bufferoffset)
+               else
                {
-                       unit->pointer_texcoord_components = components;
-                       unit->pointer_texcoord_gltype = gltype;
-                       unit->pointer_texcoord_stride = stride;
-                       unit->pointer_texcoord_pointer = pointer;
-                       unit->pointer_texcoord_vertexbuffer = vertexbuffer;
-                       unit->pointer_texcoord_offset = bufferoffset;
-                       GL_ClientActiveTexture(unitnum);
-                       GL_BindVBO(bufferobject);
-                       qglTexCoordPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
+                       // texture array unit is disabled, disable the array
+                       if (unit->arrayenabled)
+                       {
+                               unit->arrayenabled = false;
+                               GL_ClientActiveTexture(unitnum);
+                               qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
+                       }
                }
-       }
-       else
-       {
-               // texture array unit is disabled, disable the array
-               if (unit->arrayenabled)
+               break;
+       case RENDERPATH_GLES2:
+               CHECKGLERROR
+               if (pointer)
                {
-                       unit->arrayenabled = false;
-                       GL_ClientActiveTexture(unitnum);
-                       qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
+                       int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
+                       // texture array unit is enabled, enable the array
+                       if (!unit->arrayenabled)
+                       {
+                               unit->arrayenabled = true;
+                               qglEnableVertexAttribArray(unitnum+GLES2ATTRIB_TEXCOORD0);CHECKGLERROR
+                       }
+                       // texcoord array
+                       if (unit->pointer_texcoord_components != components || unit->pointer_texcoord_gltype != gltype || unit->pointer_texcoord_stride != stride || unit->pointer_texcoord_pointer != pointer || unit->pointer_texcoord_vertexbuffer != vertexbuffer || unit->pointer_texcoord_offset != bufferoffset)
+                       {
+                               unit->pointer_texcoord_components = components;
+                               unit->pointer_texcoord_gltype = gltype;
+                               unit->pointer_texcoord_stride = stride;
+                               unit->pointer_texcoord_pointer = pointer;
+                               unit->pointer_texcoord_vertexbuffer = vertexbuffer;
+                               unit->pointer_texcoord_offset = bufferoffset;
+                               GL_BindVBO(bufferobject);
+                               qglVertexAttribPointer(unitnum+GLES2ATTRIB_TEXCOORD0, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
+                       }
                }
+               else
+               {
+                       // texture array unit is disabled, disable the array
+                       if (unit->arrayenabled)
+                       {
+                               unit->arrayenabled = false;
+                               qglDisableVertexAttribArray(unitnum+GLES2ATTRIB_TEXCOORD0);CHECKGLERROR
+                       }
+               }
+               break;
+       case RENDERPATH_D3D9:
+       case RENDERPATH_D3D10:
+       case RENDERPATH_D3D11:
+       case RENDERPATH_SOFT:
+               break;
        }
 }
 
@@ -3179,6 +3425,7 @@ void R_Mesh_CopyToTexture(rtexture_t *tex, int tx, int ty, int sx, int sy, int w
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                R_Mesh_TexBind(0, tex);
                GL_ActiveTexture(0);CHECKGLERROR
                qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, sx, sy, width, height);CHECKGLERROR
@@ -3238,6 +3485,7 @@ void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
        {
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                if (!tex)
                {
                        tex = r_texture_white;
@@ -3440,6 +3688,8 @@ void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
                break;
        case RENDERPATH_SOFT:
                break;
+       case RENDERPATH_GLES2:
+               break;
        }
 }
 
@@ -3451,6 +3701,7 @@ void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, i
        {
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                // do nothing
                break;
        case RENDERPATH_GL13:
@@ -3643,6 +3894,8 @@ void R_Mesh_ResetTextureState(void)
                break;
        case RENDERPATH_SOFT:
                break;
+       case RENDERPATH_GLES2:
+               break;
        }
 }
 
@@ -3696,6 +3949,7 @@ static void R_Mesh_InitVertexDeclarations(void)
        case RENDERPATH_CGGL:
        case RENDERPATH_GL13:
        case RENDERPATH_GL11:
+       case RENDERPATH_GLES2:
                break;
        case RENDERPATH_D3D9:
                IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9elements, &r_vertex3f_d3d9decl);
@@ -3746,6 +4000,7 @@ void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, con
        {
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                if (vertexbuffer)
                {
                        R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
@@ -3859,6 +4114,7 @@ void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3
        {
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                if (!vid.useinterleavedarrays)
                {
                        R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
@@ -3945,6 +4201,7 @@ void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *ve
        {
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                if (vertexbuffer)
                {
                        R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
@@ -4058,6 +4315,7 @@ void R_Mesh_PrepareVertices_Mesh_Arrays(int numvertices, const float *vertex3f,
        {
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                if (!vid.useinterleavedarrays)
                {
                        R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
@@ -4155,6 +4413,7 @@ void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex,
        {
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                if (vertexbuffer)
                {
                        R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
index d0b132d..1de605a 100644 (file)
--- a/gl_draw.c
+++ b/gl_draw.c
@@ -1941,6 +1941,9 @@ void DrawQ_LineLoop (drawqueuemesh_t *mesh, int flags)
        case RENDERPATH_SOFT:
                //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_GLES2:
+               //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+               return;
        }
 }
 
@@ -1983,6 +1986,9 @@ void DrawQ_Line (float width, float x1, float y1, float x2, float y2, float r, f
        case RENDERPATH_SOFT:
                //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_GLES2:
+               //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+               return;
        }
 }
 
@@ -2028,6 +2034,9 @@ void DrawQ_Lines (float width, int numlines, const float *vertex3f, const float
        case RENDERPATH_SOFT:
                //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_GLES2:
+               //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+               return;
        }
 }
 
@@ -2075,6 +2084,7 @@ void R_DrawGamma(void)
        case RENDERPATH_D3D9:
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
+       case RENDERPATH_GLES2:
                if (vid_usinghwgamma || v_glslgamma.integer)
                        return;
                break;
index f3d2e6c..69b41d9 100644 (file)
@@ -3320,6 +3320,36 @@ const char *builtincgshaderstring =
 "#endif // !MODE_DEPTH_OR_SHADOW\n"
 ;
 
+/*
+=========================================================================================================================================================
+
+
+
+=========================================================================================================================================================
+
+
+
+=========================================================================================================================================================
+
+
+
+=========================================================================================================================================================
+
+
+
+=========================================================================================================================================================
+
+
+
+=========================================================================================================================================================
+
+
+
+=========================================================================================================================================================
+*/
+
+const char *builtingles2shaderstring = ""; // FIXME GLES2
+
 char *glslshaderstring = NULL;
 char *cgshaderstring = NULL;
 char *hlslshaderstring = NULL;
@@ -3418,7 +3448,6 @@ shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
 };
 #endif
 
-#ifdef SUPPORTD3D
 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
 {
        {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
@@ -3438,7 +3467,26 @@ shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
        {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
        {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
 };
-#endif
+
+shadermodeinfo_t gles2shadermodeinfo[SHADERMODE_COUNT] =
+{
+       {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_GENERIC\n", " generic"},
+       {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
+       {"gles2/default.glsl", NULL, NULL                , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
+       {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
+       {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
+       {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
+       {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
+       {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
+       {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
+       {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
+       {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
+       {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
+       {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_WATER\n", " water"},
+       {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
+       {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
+       {"gles2/default.glsl", NULL, "gles2/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
+};
 
 struct r_glsl_permutation_s;
 typedef struct r_glsl_permutation_s
@@ -3452,6 +3500,36 @@ typedef struct r_glsl_permutation_s
        qboolean compiled;
        /// 0 if compilation failed
        int program;
+       // texture units assigned to each detected uniform
+       int tex_Texture_First;
+       int tex_Texture_Second;
+       int tex_Texture_GammaRamps;
+       int tex_Texture_Normal;
+       int tex_Texture_Color;
+       int tex_Texture_Gloss;
+       int tex_Texture_Glow;
+       int tex_Texture_SecondaryNormal;
+       int tex_Texture_SecondaryColor;
+       int tex_Texture_SecondaryGloss;
+       int tex_Texture_SecondaryGlow;
+       int tex_Texture_Pants;
+       int tex_Texture_Shirt;
+       int tex_Texture_FogHeightTexture;
+       int tex_Texture_FogMask;
+       int tex_Texture_Lightmap;
+       int tex_Texture_Deluxemap;
+       int tex_Texture_Attenuation;
+       int tex_Texture_Cube;
+       int tex_Texture_Refraction;
+       int tex_Texture_Reflection;
+       int tex_Texture_ShadowMap2D;
+       int tex_Texture_CubeProjection;
+       int tex_Texture_ScreenDepth;
+       int tex_Texture_ScreenNormalMap;
+       int tex_Texture_ScreenDiffuse;
+       int tex_Texture_ScreenSpecular;
+       int tex_Texture_ReflectMask;
+       int tex_Texture_ReflectCube;
        /// locations of detected uniforms in program object, or -1 if not found
        int loc_Texture_First;
        int loc_Texture_Second;
@@ -3653,6 +3731,20 @@ static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
                memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
                return shaderstring;
        }
+       if (!strcmp(filename, "gles2/default.glsl"))
+       {
+               if (!glslshaderstring)
+               {
+                       glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
+                       if (glslshaderstring)
+                               Con_DPrintf("Loading shaders from file %s...\n", filename);
+                       else
+                               glslshaderstring = (char *)builtingles2shaderstring;
+               }
+               shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
+               memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
+               return shaderstring;
+       }
        shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
        if (shaderstring)
        {
@@ -3666,7 +3758,8 @@ static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
 {
        int i;
-       shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
+       int sampler;
+       shadermodeinfo_t *modeinfo = vid.renderpath == RENDERPATH_GLES2 ? gles2shadermodeinfo + mode : glslshadermodeinfo + mode;
        char *vertexstring, *geometrystring, *fragmentstring;
        char permutationname[256];
        int vertstrings_count = 0;
@@ -3834,37 +3927,80 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode
                p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
                p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
                // initialize the samplers to refer to the texture units we use
-               if (p->loc_Texture_First           >= 0) qglUniform1i(p->loc_Texture_First          , GL20TU_FIRST);
-               if (p->loc_Texture_Second          >= 0) qglUniform1i(p->loc_Texture_Second         , GL20TU_SECOND);
-               if (p->loc_Texture_GammaRamps      >= 0) qglUniform1i(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
-               if (p->loc_Texture_Normal          >= 0) qglUniform1i(p->loc_Texture_Normal         , GL20TU_NORMAL);
-               if (p->loc_Texture_Color           >= 0) qglUniform1i(p->loc_Texture_Color          , GL20TU_COLOR);
-               if (p->loc_Texture_Gloss           >= 0) qglUniform1i(p->loc_Texture_Gloss          , GL20TU_GLOSS);
-               if (p->loc_Texture_Glow            >= 0) qglUniform1i(p->loc_Texture_Glow           , GL20TU_GLOW);
-               if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1i(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
-               if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1i(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
-               if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1i(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
-               if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1i(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
-               if (p->loc_Texture_Pants           >= 0) qglUniform1i(p->loc_Texture_Pants          , GL20TU_PANTS);
-               if (p->loc_Texture_Shirt           >= 0) qglUniform1i(p->loc_Texture_Shirt          , GL20TU_SHIRT);
-               if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1i(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
-               if (p->loc_Texture_FogMask         >= 0) qglUniform1i(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
-               if (p->loc_Texture_Lightmap        >= 0) qglUniform1i(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
-               if (p->loc_Texture_Deluxemap       >= 0) qglUniform1i(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
-               if (p->loc_Texture_Attenuation     >= 0) qglUniform1i(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
-               if (p->loc_Texture_Cube            >= 0) qglUniform1i(p->loc_Texture_Cube           , GL20TU_CUBE);
-               if (p->loc_Texture_Refraction      >= 0) qglUniform1i(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
-               if (p->loc_Texture_Reflection      >= 0) qglUniform1i(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
-               if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1i(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
-               if (p->loc_Texture_CubeProjection  >= 0) qglUniform1i(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
-               if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1i(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
-               if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1i(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
-               if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1i(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
-               if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1i(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
-               if (p->loc_Texture_ReflectMask     >= 0) qglUniform1i(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
-               if (p->loc_Texture_ReflectCube     >= 0) qglUniform1i(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
+               p->tex_Texture_First = -1;
+               p->tex_Texture_Second = -1;
+               p->tex_Texture_GammaRamps = -1;
+               p->tex_Texture_Normal = -1;
+               p->tex_Texture_Color = -1;
+               p->tex_Texture_Gloss = -1;
+               p->tex_Texture_Glow = -1;
+               p->tex_Texture_SecondaryNormal = -1;
+               p->tex_Texture_SecondaryColor = -1;
+               p->tex_Texture_SecondaryGloss = -1;
+               p->tex_Texture_SecondaryGlow = -1;
+               p->tex_Texture_Pants = -1;
+               p->tex_Texture_Shirt = -1;
+               p->tex_Texture_FogHeightTexture = -1;
+               p->tex_Texture_FogMask = -1;
+               p->tex_Texture_Lightmap = -1;
+               p->tex_Texture_Deluxemap = -1;
+               p->tex_Texture_Attenuation = -1;
+               p->tex_Texture_Cube = -1;
+               p->tex_Texture_Refraction = -1;
+               p->tex_Texture_Reflection = -1;
+               p->tex_Texture_ShadowMap2D = -1;
+               p->tex_Texture_CubeProjection = -1;
+               p->tex_Texture_ScreenDepth = -1;
+               p->tex_Texture_ScreenNormalMap = -1;
+               p->tex_Texture_ScreenDiffuse = -1;
+               p->tex_Texture_ScreenSpecular = -1;
+               p->tex_Texture_ReflectMask = -1;
+               p->tex_Texture_ReflectCube = -1;
+               sampler = 0;
+               if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
+               if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
+               if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
+               if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
+               if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
+               if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
+               if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
+               if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
+               if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
+               if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
+               if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
+               if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
+               if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
+               if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
+               if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
+               if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
+               if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
+               if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
+               if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
+               if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
+               if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
+               if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
+               if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
+               if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
+               if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
+               if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
+               if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
+               if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
+               if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
+               if (vid.renderpath == RENDERPATH_GLES2)
+               {
+                       qglBindAttribLocation(p->program, GLES2ATTRIB_POSITION , "Attrib_Position" );
+                       qglBindAttribLocation(p->program, GLES2ATTRIB_COLOR    , "Attrib_Color"    );
+                       qglBindAttribLocation(p->program, GLES2ATTRIB_TEXCOORD0, "Attrib_TexCoord0");
+                       qglBindAttribLocation(p->program, GLES2ATTRIB_TEXCOORD1, "Attrib_TexCoord1");
+                       qglBindAttribLocation(p->program, GLES2ATTRIB_TEXCOORD2, "Attrib_TexCoord2");
+                       qglBindAttribLocation(p->program, GLES2ATTRIB_TEXCOORD3, "Attrib_TexCoord3");
+                       qglBindAttribLocation(p->program, GLES2ATTRIB_TEXCOORD4, "Attrib_TexCoord4");
+                       qglBindAttribLocation(p->program, GLES2ATTRIB_TEXCOORD5, "Attrib_TexCoord5");
+                       qglBindAttribLocation(p->program, GLES2ATTRIB_TEXCOORD6, "Attrib_TexCoord6");
+                       qglBindAttribLocation(p->program, GLES2ATTRIB_TEXCOORD7, "Attrib_TexCoord7");
+               }
                CHECKGLERROR
-               Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
+               Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
        }
        else
                Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
@@ -4945,7 +5081,7 @@ void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutatio
 void R_GLSL_Restart_f(void)
 {
        unsigned int i, limit;
-       if (glslshaderstring && glslshaderstring != builtinshaderstring)
+       if (glslshaderstring && glslshaderstring != builtinshaderstring && glslshaderstring != builtingles2shaderstring)
                Mem_Free(glslshaderstring);
        glslshaderstring = NULL;
        if (cgshaderstring && cgshaderstring != builtincgshaderstring)
@@ -4988,6 +5124,7 @@ void R_GLSL_Restart_f(void)
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
        case RENDERPATH_GL20:
+       case RENDERPATH_GLES2:
                {
                        r_glsl_permutation_t *p;
                        r_glsl_permutation = NULL;
@@ -5058,6 +5195,23 @@ void R_GLSL_DumpShader_f(void)
        else
                Con_Printf("failed to write to glsl/default.glsl\n");
 
+       file = FS_OpenRealFile("gles2/default.glsl", "w", false);
+       if (file)
+       {
+               FS_Print(file, "/* The engine may define the following macros:\n");
+               FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
+               for (i = 0;i < SHADERMODE_COUNT;i++)
+                       FS_Print(file, glslshadermodeinfo[i].pretext);
+               for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
+                       FS_Print(file, shaderpermutationinfo[i].pretext);
+               FS_Print(file, "*/\n");
+               FS_Print(file, builtingles2shaderstring);
+               FS_Close(file);
+               Con_Printf("gles2/default.glsl written\n");
+       }
+       else
+               Con_Printf("failed to write to glsl/default.glsl\n");
+
 #ifdef SUPPORTCG
        file = FS_OpenRealFile("cg/default.cg", "w", false);
        if (file)
@@ -5077,7 +5231,6 @@ void R_GLSL_DumpShader_f(void)
                Con_Printf("failed to write to cg/default.cg\n");
 #endif
 
-#ifdef SUPPORTD3D
        file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
        if (file)
        {
@@ -5094,7 +5247,6 @@ void R_GLSL_DumpShader_f(void)
        }
        else
                Con_Printf("failed to write to hlsl/default.hlsl\n");
-#endif
 }
 
 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
@@ -5117,9 +5269,10 @@ void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemod
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
        case RENDERPATH_GL20:
+       case RENDERPATH_GLES2:
                R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
-               R_Mesh_TexBind(GL20TU_FIRST , first );
-               R_Mesh_TexBind(GL20TU_SECOND, second);
+               R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
+               R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
                break;
        case RENDERPATH_CGGL:
 #ifdef SUPPORTCG
@@ -5163,6 +5316,7 @@ void R_SetupShader_DepthOrShadow(void)
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
        case RENDERPATH_GL20:
+       case RENDERPATH_GLES2:
                R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
                break;
        case RENDERPATH_CGGL:
@@ -5199,6 +5353,7 @@ void R_SetupShader_ShowDepth(void)
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
        case RENDERPATH_GL20:
+       case RENDERPATH_GLES2:
                R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
                break;
        case RENDERPATH_CGGL:
@@ -5837,6 +5992,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
        case RENDERPATH_GL20:
+       case RENDERPATH_GLES2:
                if (!vid.useinterleavedarrays)
                {
                        RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
@@ -5942,47 +6098,47 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
                if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
 
-       //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
-       //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
-       //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
-               if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
-               if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
-               if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
-               if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
-               if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
-               if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
-               if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
-               if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
-               if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
-               if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
-               if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
-               if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
-               if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
-               if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
-               if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
-               if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
-               if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
+               if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
+               if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
+               if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
+               if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
+               if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
+               if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
+               if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
+               if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
+               if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
+               if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
+               if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
+               if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
+               if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
+               if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
+               if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
+               if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
+               if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
+               if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
+               if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
+               if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
                if (rsurfacepass == RSURFPASS_BACKGROUND)
                {
-                       if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
-                       else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
-                       if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
+                       if (r_glsl_permutation->tex_Texture_Refraction  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
+                       if (r_glsl_permutation->tex_Texture_First       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
+                       if (r_glsl_permutation->tex_Texture_Reflection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
                }
                else
                {
-                       if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
+                       if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
                }
-//             if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
-//             if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
-               if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
-               if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
+               if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
+               if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
+               if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
+               if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
                if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
                {
-                       if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
+                       if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
                        if (rsurface.rtlight)
                        {
-                               if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
-                               if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
+                               if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
+                               if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
                        }
                }
                CHECKGLERROR
@@ -6367,6 +6523,7 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
        case RENDERPATH_GL20:
+       case RENDERPATH_GLES2:
                R_SetupShader_SetPermutationGLSL(mode, permutation);
                if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
                if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
@@ -6377,14 +6534,14 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
                if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
                if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1f(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
                if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2f(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
-               if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
-
-               if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
-               if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
-               if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
-               if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
-               if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
-               if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
+               if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
+
+               if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
+               if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
+               if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
+               if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
+               if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
+               if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
                break;
        case RENDERPATH_CGGL:
 #ifdef SUPPORTCG
@@ -7298,6 +7455,14 @@ void gl_main_start(void)
                r_loadgloss = false;
                r_loadfog = true;
                break;
+       case RENDERPATH_GLES2:
+               Cvar_SetValueQuick(&r_textureunits, 1);
+               Cvar_SetValueQuick(&gl_combine, 1);
+               Cvar_SetValueQuick(&r_glsl, 1);
+               r_loadnormalmap = true;
+               r_loadgloss = false;
+               r_loadfog = false;
+               break;
        }
 
        R_AnimCache_Free();
@@ -7377,6 +7542,9 @@ void gl_main_shutdown(void)
                break;
        case RENDERPATH_SOFT:
                break;
+       case RENDERPATH_GLES2:
+               //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+               break;
        }
 
        r_numqueries = 0;
@@ -7993,6 +8161,7 @@ void R_AnimCache_CacheVisibleEntities(void)
        case RENDERPATH_D3D9:
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
+       case RENDERPATH_GLES2:
                break;
        case RENDERPATH_GL13:
        case RENDERPATH_GL11:
@@ -8328,6 +8497,7 @@ static void R_View_SetFrustum(const int *scissor)
                        case RENDERPATH_GL13:
                        case RENDERPATH_GL20:
                        case RENDERPATH_CGGL:
+                       case RENDERPATH_GLES2:
                                // non-flipped y coordinates
                                fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
                                fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
@@ -8594,6 +8764,10 @@ void R_EntityMatrix(const matrix4x4_t *matrix)
                        DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
                        DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
                        break;
+               case RENDERPATH_GLES2:
+                       if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
+                       if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
+                       break;
                }
        }
 }
@@ -8626,6 +8800,7 @@ void R_ResetViewRendering2D(void)
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
                break;
        case RENDERPATH_D3D9:
@@ -8662,6 +8837,7 @@ void R_ResetViewRendering3D(void)
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
                break;
        case RENDERPATH_D3D9:
@@ -8712,6 +8888,7 @@ static void R_Water_StartFrame(void)
                break;
        case RENDERPATH_GL13:
        case RENDERPATH_GL11:
+       case RENDERPATH_GLES2:
                return;
        }
 
@@ -9078,6 +9255,7 @@ void R_Bloom_StartFrame(void)
                break;
        case RENDERPATH_GL13:
        case RENDERPATH_GL11:
+       case RENDERPATH_GLES2:
                return;
        }
 
@@ -9176,6 +9354,7 @@ void R_Bloom_StartFrame(void)
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
                break;
        case RENDERPATH_D3D9:
        case RENDERPATH_D3D10:
@@ -9219,6 +9398,7 @@ void R_Bloom_CopyBloomTexture(float colorscale)
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
                R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
                break;
        case RENDERPATH_D3D9:
@@ -9397,6 +9577,7 @@ static void R_BlendView(void)
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
                permutation =
                          (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
                        | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
@@ -9451,6 +9632,7 @@ static void R_BlendView(void)
                                        case RENDERPATH_GL20:
                                        case RENDERPATH_CGGL:
                                        case RENDERPATH_SOFT:
+                                       case RENDERPATH_GLES2:
                                                R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
                                                break;
                                        case RENDERPATH_D3D9:
@@ -9514,20 +9696,21 @@ static void R_BlendView(void)
                switch(vid.renderpath)
                {
                case RENDERPATH_GL20:
+               case RENDERPATH_GLES2:
                        R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
                        R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
-                       if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
-                       if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
-                       if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
-                       if (r_glsl_permutation->loc_ViewTintColor      >= 0) qglUniform4f(r_glsl_permutation->loc_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
-                       if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
-                       if (r_glsl_permutation->loc_UserVec1           >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
-                       if (r_glsl_permutation->loc_UserVec2           >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
-                       if (r_glsl_permutation->loc_UserVec3           >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
-                       if (r_glsl_permutation->loc_UserVec4           >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
-                       if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
-                       if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
-                       if (r_glsl_permutation->loc_BloomColorSubtract    >= 0) qglUniform4f(r_glsl_permutation->loc_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
+                       if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
+                       if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
+                       if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
+                       if (r_glsl_permutation->loc_ViewTintColor           >= 0) qglUniform4f(r_glsl_permutation->loc_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
+                       if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
+                       if (r_glsl_permutation->loc_UserVec1                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
+                       if (r_glsl_permutation->loc_UserVec2                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
+                       if (r_glsl_permutation->loc_UserVec3                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
+                       if (r_glsl_permutation->loc_UserVec4                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
+                       if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
+                       if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
+                       if (r_glsl_permutation->loc_BloomColorSubtract      >= 0) qglUniform4f(r_glsl_permutation->loc_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
                        break;
                case RENDERPATH_CGGL:
 #ifdef SUPPORTCG
@@ -9742,6 +9925,7 @@ void R_UpdateVariables(void)
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
                if(v_glslgamma.integer && !vid_gammatables_trivial)
                {
                        if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
@@ -13193,6 +13377,7 @@ static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
                R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
                break;
        case RENDERPATH_GL13:
@@ -13222,6 +13407,7 @@ static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
                R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
                break;
        case RENDERPATH_GL13:
@@ -13260,6 +13446,7 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const
                case RENDERPATH_D3D10:
                case RENDERPATH_D3D11:
                case RENDERPATH_SOFT:
+               case RENDERPATH_GLES2:
                        RSurf_ActiveModelEntity(ent, true, true, false);
                        break;
                case RENDERPATH_GL13:
@@ -14297,6 +14484,9 @@ void R_DrawDebugModel(void)
        case RENDERPATH_SOFT:
                //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                return;
+       case RENDERPATH_GLES2:
+               //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+               break;
        }
 
        flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
@@ -14588,6 +14778,7 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr
                case RENDERPATH_D3D10:
                case RENDERPATH_D3D11:
                case RENDERPATH_SOFT:
+               case RENDERPATH_GLES2:
                        RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
                        break;
                case RENDERPATH_GL13:
@@ -14606,6 +14797,7 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr
                case RENDERPATH_D3D10:
                case RENDERPATH_D3D11:
                case RENDERPATH_SOFT:
+               case RENDERPATH_GLES2:
                        RSurf_ActiveModelEntity(ent, true, true, false);
                        break;
                case RENDERPATH_GL13:
index 6fe868f..03dc5ef 100644 (file)
@@ -303,6 +303,7 @@ void R_FreeTexture(rtexture_t *rt)
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                if (glt->texnum)
                {
                        CHECKGLERROR
@@ -456,6 +457,7 @@ static void GL_TextureMode_f (void)
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                // change all the existing mipmap texture objects
                // FIXME: force renderer(/client/something?) restart instead?
                CHECKGLERROR
@@ -584,6 +586,7 @@ static void GL_Texture_CalcImageSize(int texturetype, int flags, int miplevel, i
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
                break;
        case RENDERPATH_D3D9:
 #if 0
@@ -701,6 +704,7 @@ static void r_textures_start(void)
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                // LordHavoc: allow any alignment
                CHECKGLERROR
                qglPixelStorei(GL_UNPACK_ALIGNMENT, 1);CHECKGLERROR
@@ -768,6 +772,7 @@ static void r_textures_devicelost(void)
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
                case RENDERPATH_CGGL:
+               case RENDERPATH_GLES2:
                        break;
                case RENDERPATH_D3D9:
 #ifdef SUPPORTD3D
@@ -810,6 +815,7 @@ static void r_textures_devicerestored(void)
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
                case RENDERPATH_CGGL:
+               case RENDERPATH_GLES2:
                        break;
                case RENDERPATH_D3D9:
 #ifdef SUPPORTD3D
@@ -920,6 +926,7 @@ void R_Textures_Frame (void)
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
                case RENDERPATH_CGGL:
+               case RENDERPATH_GLES2:
                        CHECKGLERROR
                        GL_ActiveTexture(0);
                        for (pool = gltexturepoolchain;pool;pool = pool->next)
@@ -1075,6 +1082,7 @@ static void R_UploadPartialTexture(gltexture_t *glt, const unsigned char *data,
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                {
                        int oldbindtexnum;
                        CHECKGLERROR
@@ -1187,6 +1195,7 @@ static void R_UploadFullTexture(gltexture_t *glt, const unsigned char *data)
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                CHECKGLERROR
 
                // we need to restore the texture binding after finishing the upload
@@ -1609,6 +1618,7 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *iden
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                CHECKGLERROR
                qglGenTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR
                break;
@@ -2241,6 +2251,7 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                CHECKGLERROR
                GL_ActiveTexture(0);
                oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]);
@@ -2293,6 +2304,7 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
                case RENDERPATH_CGGL:
+               case RENDERPATH_GLES2:
                        if (bytesperblock)
                        {
                                qglCompressedTexImage2DARB(GL_TEXTURE_2D, mip, glt->glinternalformat, mipwidth, mipheight, 0, mipsize, mippixels);CHECKGLERROR
@@ -2349,6 +2361,7 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
+       case RENDERPATH_GLES2:
                if (dds_miplevels >= 1 && !mipcomplete)
                {
                        // need to set GL_TEXTURE_MAX_LEVEL
index e58ba5c..4f40987 100644 (file)
@@ -5628,14 +5628,27 @@ static void Mod_Q3BSP_LoadPVS(lump_t *l)
 static void Mod_Q3BSP_LightPoint(dp_model_t *model, const vec3_t p, vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal)
 {
        int i, j, k, index[3];
-       float transformed[3], blend1, blend2, blend, stylescale;
+       float transformed[3], blend1, blend2, blend, stylescale = 1;
        q3dlightgrid_t *a, *s;
 
        // scale lighting by lightstyle[0] so that darkmode in dpmod works properly
-       if (vid.renderpath == RENDERPATH_GL20)
+       switch(vid.renderpath)
+       {
+       case RENDERPATH_GL20:
+       case RENDERPATH_CGGL:
+       case RENDERPATH_D3D9:
+       case RENDERPATH_D3D10:
+       case RENDERPATH_D3D11:
+       case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
+               // LordHavoc: FIXME: is this true?
                stylescale = 1; // added while render
-       else
+               break;
+       case RENDERPATH_GL11:
+       case RENDERPATH_GL13:
                stylescale = r_refdef.scene.rtlightstylevalue[0];
+               break;
+       }
 
        if (!model->brushq3.num_lightgrid)
        {
index c54235e..9f7986a 100644 (file)
@@ -437,6 +437,8 @@ void R_Shadow_SetShadowMode(void)
                        break;
                case RENDERPATH_GL11:
                        break;
+               case RENDERPATH_GLES2:
+                       break;
                }
        }
 }
@@ -1900,6 +1902,7 @@ void R_Shadow_RenderMode_Begin(void)
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
                r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_GLSL;
                break;
        case RENDERPATH_GL13:
@@ -2105,6 +2108,7 @@ init_done:
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
                GL_CullFace(r_refdef.view.cullface_back);
                // OpenGL lets us scissor larger than the viewport, so go ahead and clear all views at once
                if ((clear & ((2 << side) - 1)) == (1 << side)) // only clear if the side is the first in the mask
@@ -2677,6 +2681,7 @@ void R_Shadow_RenderLighting(int texturenumsurfaces, const msurface_t **textures
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
                case RENDERPATH_CGGL:
+               case RENDERPATH_GLES2:
                        qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
                        break;
                case RENDERPATH_D3D9:
@@ -2723,6 +2728,7 @@ void R_Shadow_RenderLighting(int texturenumsurfaces, const msurface_t **textures
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
                case RENDERPATH_CGGL:
+               case RENDERPATH_GLES2:
                        qglBlendEquationEXT(GL_FUNC_ADD_EXT);
                        break;
                case RENDERPATH_D3D9:
@@ -3890,6 +3896,7 @@ void R_Shadow_PrepareLights(void)
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
                if (!r_shadow_deferred.integer || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_STENCIL || !vid.support.ext_framebuffer_object || vid.maxdrawbuffers < 2)
                {
                        r_shadow_usingdeferredprepass = false;
@@ -4283,6 +4290,7 @@ void R_DrawModelShadowMaps(void)
        case RENDERPATH_GL20:
        case RENDERPATH_CGGL:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
                break;
        case RENDERPATH_D3D9:
        case RENDERPATH_D3D10:
@@ -4487,6 +4495,9 @@ void R_BeginCoronaQuery(rtlight_t *rtlight, float scale, qboolean usequery)
                case RENDERPATH_SOFT:
                        //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                        break;
+               case RENDERPATH_GLES2:
+                       //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+                       break;
                }
        }
        rtlight->corona_visibility = bound(0, (zdist - 32) / 32, 1);
@@ -4524,6 +4535,9 @@ void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
                case RENDERPATH_SOFT:
                        //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                        break;
+               case RENDERPATH_GLES2:
+                       //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+                       break;
                }
                //Con_Printf("%i of %i pixels\n", (int)visiblepixels, (int)allpixels);
                if (visiblepixels < 1 || allpixels < 1)
@@ -4551,6 +4565,7 @@ void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
                        case RENDERPATH_GL13:
                        case RENDERPATH_GL20:
                        case RENDERPATH_CGGL:
+                       case RENDERPATH_GLES2:
                                qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
                                break;
                        case RENDERPATH_D3D9:
@@ -4580,6 +4595,7 @@ void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
                        case RENDERPATH_GL13:
                        case RENDERPATH_GL20:
                        case RENDERPATH_CGGL:
+                       case RENDERPATH_GLES2:
                                qglBlendEquationEXT(GL_FUNC_ADD_EXT);
                                break;
                        case RENDERPATH_D3D9:
@@ -4664,8 +4680,13 @@ void R_Shadow_DrawCoronas(void)
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
        case RENDERPATH_SOFT:
+               usequery = false;
                //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
+       case RENDERPATH_GLES2:
+               usequery = false;
+               //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+               break;
        }
        for (lightindex = 0;lightindex < range;lightindex++)
        {
diff --git a/vid.h b/vid.h
index af084a6..cb6775d 100644 (file)
--- a/vid.h
+++ b/vid.h
@@ -37,7 +37,8 @@ typedef enum renderpath_e
        RENDERPATH_D3D9,
        RENDERPATH_D3D10,
        RENDERPATH_D3D11,
-       RENDERPATH_SOFT
+       RENDERPATH_SOFT,
+       RENDERPATH_GLES2
 }
 renderpath_t;
 
index 125713b..3394cb5 100644 (file)
--- a/vid_sdl.c
+++ b/vid_sdl.c
@@ -1108,7 +1108,7 @@ void GLES_Init(void)
        vid.teximageunits = bound(1, vid.teximageunits, MAX_TEXTUREUNITS);
        vid.texarrayunits = bound(1, vid.texarrayunits, MAX_TEXTUREUNITS);
        Con_DPrintf("Using GLES2.0 rendering path - %i texture matrix, %i texture images, %i texcoords%s\n", vid.texunits, vid.teximageunits, vid.texarrayunits, vid.support.ext_framebuffer_object ? ", shadowmapping supported" : "");
-       vid.renderpath = RENDERPATH_GL20;
+       vid.renderpath = RENDERPATH_GLES2;
        vid.useinterleavedarrays = false;
 
        // VorteX: set other info (maybe place them in VID_InitMode?)
@@ -1831,6 +1831,7 @@ void VID_Finish (void)
                case RENDERPATH_GL13:
                case RENDERPATH_GL20:
                case RENDERPATH_CGGL:
+               case RENDERPATH_GLES2:
                        CHECKGLERROR
                        if (r_speeds.integer == 2 || gl_finish.integer)
                        {
index ac44a78..5b62b9b 100644 (file)
@@ -261,7 +261,7 @@ void (GLAPIENTRY *qglActiveStencilFaceEXT)(GLenum);
 
 void (GLAPIENTRY *qglDeleteShader)(GLuint obj);
 void (GLAPIENTRY *qglDeleteProgram)(GLuint obj);
-GLuint (GLAPIENTRY *qglGetHandle)(GLenum pname);
+//GLuint (GLAPIENTRY *qglGetHandle)(GLenum pname);
 void (GLAPIENTRY *qglDetachShader)(GLuint containerObj, GLuint attachedObj);
 GLuint (GLAPIENTRY *qglCreateShader)(GLenum shaderType);
 void (GLAPIENTRY *qglShaderSource)(GLuint shaderObj, GLsizei count, const GLchar **string, const GLint *length);
@@ -645,7 +645,7 @@ static dllfunction_t gl20shaderfuncs[] =
 {
        {"glDeleteShader", (void **) &qglDeleteShader},
        {"glDeleteProgram", (void **) &qglDeleteProgram},
-       {"glGetHandle", (void **) &qglGetHandle},
+//     {"glGetHandle", (void **) &qglGetHandle},
        {"glDetachShader", (void **) &qglDetachShader},
        {"glCreateShader", (void **) &qglCreateShader},
        {"glShaderSource", (void **) &qglShaderSource},
@@ -1058,6 +1058,7 @@ void VID_UpdateGamma(qboolean force, int rampsize)
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
                if (v_glslgamma.integer)
                        wantgamma = 0;
                break;