+void R_Mesh_TexBindAll(unsigned int unitnum, int tex1d, int tex2d, int tex3d, int texcubemap)
+{
+ gltextureunit_t *unit = gl_state.units + unitnum;
+ if (unitnum >= backendimageunits)
+ return;
+ // update 1d texture binding
+ if (unit->t1d != tex1d)
+ {
+ GL_ActiveTexture(unitnum);
+ if (unitnum < backendunits)
+ {
+ if (tex1d)
+ {
+ if (unit->t1d == 0)
+ {
+ qglEnable(GL_TEXTURE_1D);CHECKGLERROR
+ }
+ }
+ else
+ {
+ if (unit->t1d)
+ {
+ qglDisable(GL_TEXTURE_1D);CHECKGLERROR
+ }
+ }
+ }
+ unit->t1d = tex1d;
+ qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
+ }
+ // update 2d texture binding
+ if (unit->t2d != tex2d)
+ {
+ GL_ActiveTexture(unitnum);
+ if (unitnum < backendunits)
+ {
+ if (tex2d)
+ {
+ if (unit->t2d == 0)
+ {
+ qglEnable(GL_TEXTURE_2D);CHECKGLERROR
+ }
+ }
+ else
+ {
+ if (unit->t2d)
+ {
+ qglDisable(GL_TEXTURE_2D);CHECKGLERROR
+ }
+ }
+ }
+ unit->t2d = tex2d;
+ qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
+ }
+ // update 3d texture binding
+ if (unit->t3d != tex3d)
+ {
+ GL_ActiveTexture(unitnum);
+ if (unitnum < backendunits)
+ {
+ if (tex3d)
+ {
+ if (unit->t3d == 0)
+ {
+ qglEnable(GL_TEXTURE_3D);CHECKGLERROR
+ }
+ }
+ else
+ {
+ if (unit->t3d)
+ {
+ qglDisable(GL_TEXTURE_3D);CHECKGLERROR
+ }
+ }
+ }
+ unit->t3d = tex3d;
+ qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
+ }
+ // update cubemap texture binding
+ if (unit->tcubemap != texcubemap)
+ {
+ GL_ActiveTexture(unitnum);
+ if (unitnum < backendunits)
+ {
+ if (texcubemap)
+ {
+ if (unit->tcubemap == 0)
+ {
+ qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
+ }
+ }
+ else
+ {
+ if (unit->tcubemap)
+ {
+ qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
+ }
+ }
+ }
+ unit->tcubemap = texcubemap;
+ qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
+ }
+}
+
+void R_Mesh_TexBind1D(unsigned int unitnum, int texnum)
+{
+ gltextureunit_t *unit = gl_state.units + unitnum;
+ if (unitnum >= backendimageunits)
+ return;
+ // update 1d texture binding
+ if (unit->t1d != texnum)
+ {
+ GL_ActiveTexture(unitnum);
+ if (unitnum < backendunits)
+ {
+ if (texnum)
+ {
+ if (unit->t1d == 0)
+ {
+ qglEnable(GL_TEXTURE_1D);CHECKGLERROR
+ }
+ }
+ else
+ {
+ if (unit->t1d)
+ {
+ qglDisable(GL_TEXTURE_1D);CHECKGLERROR
+ }
+ }
+ }
+ unit->t1d = texnum;
+ qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
+ }
+ // update 2d texture binding
+ if (unit->t2d)
+ {
+ GL_ActiveTexture(unitnum);
+ if (unitnum < backendunits)
+ {
+ if (unit->t2d)
+ {
+ qglDisable(GL_TEXTURE_2D);CHECKGLERROR
+ }
+ }
+ unit->t2d = 0;
+ qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
+ }
+ // update 3d texture binding
+ if (unit->t3d)
+ {
+ GL_ActiveTexture(unitnum);
+ if (unitnum < backendunits)
+ {
+ if (unit->t3d)
+ {
+ qglDisable(GL_TEXTURE_3D);CHECKGLERROR
+ }
+ }
+ unit->t3d = 0;
+ qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
+ }
+ // update cubemap texture binding
+ if (unit->tcubemap)
+ {
+ GL_ActiveTexture(unitnum);
+ if (unitnum < backendunits)
+ {
+ if (unit->tcubemap)
+ {
+ qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
+ }
+ }
+ unit->tcubemap = 0;
+ qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
+ }
+}
+
+void R_Mesh_TexBind(unsigned int unitnum, int texnum)
+{
+ gltextureunit_t *unit = gl_state.units + unitnum;
+ if (unitnum >= backendimageunits)
+ return;
+ // update 1d texture binding
+ if (unit->t1d)
+ {
+ GL_ActiveTexture(unitnum);
+ if (unitnum < backendunits)
+ {
+ if (unit->t1d)
+ {
+ qglDisable(GL_TEXTURE_1D);CHECKGLERROR
+ }
+ }
+ unit->t1d = 0;
+ qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
+ }
+ // update 2d texture binding
+ if (unit->t2d != texnum)
+ {
+ GL_ActiveTexture(unitnum);
+ if (unitnum < backendunits)
+ {
+ if (texnum)
+ {
+ if (unit->t2d == 0)
+ {
+ qglEnable(GL_TEXTURE_2D);CHECKGLERROR
+ }
+ }
+ else
+ {
+ if (unit->t2d)
+ {
+ qglDisable(GL_TEXTURE_2D);CHECKGLERROR
+ }
+ }
+ }
+ unit->t2d = texnum;
+ qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
+ }
+ // update 3d texture binding
+ if (unit->t3d)
+ {
+ GL_ActiveTexture(unitnum);
+ if (unitnum < backendunits)
+ {
+ if (unit->t3d)
+ {
+ qglDisable(GL_TEXTURE_3D);CHECKGLERROR
+ }
+ }
+ unit->t3d = 0;
+ qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
+ }
+ // update cubemap texture binding
+ if (unit->tcubemap != 0)
+ {
+ GL_ActiveTexture(unitnum);
+ if (unitnum < backendunits)
+ {
+ if (unit->tcubemap)
+ {
+ qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
+ }
+ }
+ unit->tcubemap = 0;
+ qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
+ }
+}
+
+void R_Mesh_TexBind3D(unsigned int unitnum, int texnum)
+{
+ gltextureunit_t *unit = gl_state.units + unitnum;
+ if (unitnum >= backendimageunits)
+ return;
+ // update 1d texture binding
+ if (unit->t1d)
+ {
+ GL_ActiveTexture(unitnum);
+ if (unitnum < backendunits)
+ {
+ if (unit->t1d)
+ {
+ qglDisable(GL_TEXTURE_1D);CHECKGLERROR
+ }
+ }
+ unit->t1d = 0;
+ qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
+ }
+ // update 2d texture binding
+ if (unit->t2d)
+ {
+ GL_ActiveTexture(unitnum);
+ if (unitnum < backendunits)
+ {
+ if (unit->t2d)
+ {
+ qglDisable(GL_TEXTURE_2D);CHECKGLERROR
+ }
+ }
+ unit->t2d = 0;
+ qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
+ }
+ // update 3d texture binding
+ if (unit->t3d != texnum)
+ {
+ GL_ActiveTexture(unitnum);
+ if (unitnum < backendunits)
+ {
+ if (texnum)
+ {
+ if (unit->t3d == 0)
+ {
+ qglEnable(GL_TEXTURE_3D);CHECKGLERROR
+ }
+ }
+ else
+ {
+ if (unit->t3d)
+ {
+ qglDisable(GL_TEXTURE_3D);CHECKGLERROR
+ }
+ }
+ }
+ unit->t3d = texnum;
+ qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
+ }
+ // update cubemap texture binding
+ if (unit->tcubemap != 0)
+ {
+ GL_ActiveTexture(unitnum);
+ if (unitnum < backendunits)
+ {
+ if (unit->tcubemap)
+ {
+ qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
+ }
+ }
+ unit->tcubemap = 0;
+ qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
+ }
+}
+
+void R_Mesh_TexBindCubeMap(unsigned int unitnum, int texnum)
+{
+ gltextureunit_t *unit = gl_state.units + unitnum;
+ if (unitnum >= backendimageunits)
+ return;
+ // update 1d texture binding
+ if (unit->t1d)
+ {
+ GL_ActiveTexture(unitnum);
+ if (unitnum < backendunits)
+ {
+ if (unit->t1d)
+ {
+ qglDisable(GL_TEXTURE_1D);CHECKGLERROR
+ }
+ }
+ unit->t1d = 0;
+ qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
+ }
+ // update 2d texture binding
+ if (unit->t2d)
+ {
+ GL_ActiveTexture(unitnum);
+ if (unitnum < backendunits)
+ {
+ if (unit->t2d)
+ {
+ qglDisable(GL_TEXTURE_2D);CHECKGLERROR
+ }
+ }
+ unit->t2d = 0;
+ qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
+ }
+ // update 3d texture binding
+ if (unit->t3d)
+ {
+ GL_ActiveTexture(unitnum);
+ if (unitnum < backendunits)
+ {
+ if (unit->t3d)
+ {
+ qglDisable(GL_TEXTURE_3D);CHECKGLERROR
+ }
+ }
+ unit->t3d = 0;
+ qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
+ }
+ // update cubemap texture binding
+ if (unit->tcubemap != texnum)
+ {
+ GL_ActiveTexture(unitnum);
+ if (unitnum < backendunits)
+ {
+ if (texnum)
+ {
+ if (unit->tcubemap == 0)
+ {
+ qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
+ }
+ }
+ else
+ {
+ if (unit->tcubemap)
+ {
+ qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
+ }
+ }
+ }
+ unit->tcubemap = texnum;
+ qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
+ }
+}
+
+void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
+{
+ gltextureunit_t *unit = gl_state.units + unitnum;
+ if (matrix->m[3][3])
+ {
+ // texmatrix specified, check if it is different
+ if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t)))
+ {
+ double glmatrix[16];
+ unit->texmatrixenabled = true;
+ unit->matrix = *matrix;
+ CHECKGLERROR
+ Matrix4x4_ToArrayDoubleGL(&unit->matrix, glmatrix);
+ qglMatrixMode(GL_TEXTURE);CHECKGLERROR
+ GL_ActiveTexture(unitnum);
+ qglLoadMatrixd(glmatrix);CHECKGLERROR
+ qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
+ }
+ }
+ else
+ {
+ // no texmatrix specified, revert to identity
+ if (unit->texmatrixenabled)
+ {
+ unit->texmatrixenabled = false;
+ CHECKGLERROR
+ qglMatrixMode(GL_TEXTURE);CHECKGLERROR
+ GL_ActiveTexture(unitnum);
+ qglLoadIdentity();CHECKGLERROR
+ qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
+ }
+ }
+}
+
+void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale)
+{
+ gltextureunit_t *unit = gl_state.units + unitnum;
+ CHECKGLERROR
+ if (gl_combine.integer)
+ {
+ // GL_ARB_texture_env_combine
+ if (!combinergb)
+ combinergb = GL_MODULATE;
+ if (!combinealpha)
+ combinealpha = GL_MODULATE;
+ if (!rgbscale)
+ rgbscale = 1;
+ if (!alphascale)
+ alphascale = 1;
+ if (unit->combinergb != combinergb)
+ {
+ unit->combinergb = combinergb;
+ GL_ActiveTexture(unitnum);
+ qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
+ }
+ if (unit->combinealpha != combinealpha)
+ {
+ unit->combinealpha = combinealpha;
+ GL_ActiveTexture(unitnum);
+ qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
+ }
+ if (unit->rgbscale != rgbscale)
+ {
+ GL_ActiveTexture(unitnum);
+ qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (unit->rgbscale = rgbscale));CHECKGLERROR
+ }
+ if (unit->alphascale != alphascale)
+ {
+ GL_ActiveTexture(unitnum);
+ qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, (unit->alphascale = alphascale));CHECKGLERROR
+ }
+ }
+ else
+ {
+ // normal GL texenv
+ if (!combinergb)
+ combinergb = GL_MODULATE;
+ if (unit->combinergb != combinergb)
+ {
+ unit->combinergb = combinergb;
+ GL_ActiveTexture(unitnum);
+ qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combinergb);CHECKGLERROR
+ }
+ }
+}
+
+void R_Mesh_TextureState(const rmeshstate_t *m)
+{
+ unsigned int i;
+
+ BACKENDACTIVECHECK
+
+ CHECKGLERROR
+ if (gl_backend_rebindtextures)
+ {
+ gl_backend_rebindtextures = false;
+ GL_SetupTextureState();
+ CHECKGLERROR
+ }
+
+ for (i = 0;i < backendimageunits;i++)
+ R_Mesh_TexBindAll(i, m->tex1d[i], m->tex[i], m->tex3d[i], m->texcubemap[i]);
+ for (i = 0;i < backendarrayunits;i++)
+ {
+ if (m->pointer_texcoord3f[i])
+ R_Mesh_TexCoordPointer(i, 3, m->pointer_texcoord3f[i], m->pointer_texcoord_bufferobject[i], m->pointer_texcoord_bufferoffset[i]);
+ else
+ R_Mesh_TexCoordPointer(i, 2, m->pointer_texcoord[i], m->pointer_texcoord_bufferobject[i], m->pointer_texcoord_bufferoffset[i]);
+ }
+ for (i = 0;i < backendunits;i++)
+ {
+ R_Mesh_TexMatrix(i, &m->texmatrix[i]);
+ R_Mesh_TexCombine(i, m->texcombinergb[i], m->texcombinealpha[i], m->texrgbscale[i], m->texalphascale[i]);
+ }
+ CHECKGLERROR
+}
+
+void R_Mesh_ResetTextureState(void)
+{
+ unsigned int unitnum;
+
+ BACKENDACTIVECHECK
+
+ CHECKGLERROR
+ if (gl_backend_rebindtextures)
+ {
+ gl_backend_rebindtextures = false;
+ GL_SetupTextureState();
+ CHECKGLERROR
+ }
+
+ for (unitnum = 0;unitnum < backendimageunits;unitnum++)
+ {
+ gltextureunit_t *unit = gl_state.units + unitnum;
+ // update 1d texture binding
+ if (unit->t1d)
+ {
+ GL_ActiveTexture(unitnum);
+ if (unitnum < backendunits)
+ {
+ qglDisable(GL_TEXTURE_1D);CHECKGLERROR
+ }
+ unit->t1d = 0;
+ qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
+ }
+ // update 2d texture binding
+ if (unit->t2d)
+ {
+ GL_ActiveTexture(unitnum);
+ if (unitnum < backendunits)
+ {
+ qglDisable(GL_TEXTURE_2D);CHECKGLERROR
+ }
+ unit->t2d = 0;
+ qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
+ }
+ // update 3d texture binding
+ if (unit->t3d)
+ {
+ GL_ActiveTexture(unitnum);
+ if (unitnum < backendunits)
+ {
+ qglDisable(GL_TEXTURE_3D);CHECKGLERROR
+ }
+ unit->t3d = 0;
+ qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
+ }
+ // update cubemap texture binding
+ if (unit->tcubemap)
+ {
+ GL_ActiveTexture(unitnum);
+ if (unitnum < backendunits)
+ {
+ qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
+ }
+ unit->tcubemap = 0;
+ qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
+ }
+ }
+ for (unitnum = 0;unitnum < backendarrayunits;unitnum++)
+ {
+ gltextureunit_t *unit = gl_state.units + unitnum;
+ // texture array unit is disabled, disable the array
+ if (unit->arrayenabled)
+ {
+ unit->arrayenabled = false;
+ GL_ClientActiveTexture(unitnum);
+ qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
+ }
+ }
+ for (unitnum = 0;unitnum < backendunits;unitnum++)
+ {
+ gltextureunit_t *unit = gl_state.units + unitnum;
+ // no texmatrix specified, revert to identity
+ if (unit->texmatrixenabled)
+ {
+ unit->texmatrixenabled = false;
+ CHECKGLERROR
+ qglMatrixMode(GL_TEXTURE);CHECKGLERROR
+ GL_ActiveTexture(unitnum);
+ qglLoadIdentity();CHECKGLERROR
+ qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
+ }
+ if (gl_combine.integer)
+ {
+ // GL_ARB_texture_env_combine
+ if (unit->combinergb != GL_MODULATE)
+ {
+ unit->combinergb = GL_MODULATE;
+ GL_ActiveTexture(unitnum);
+ qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
+ }
+ if (unit->combinealpha != GL_MODULATE)
+ {
+ unit->combinealpha = GL_MODULATE;
+ GL_ActiveTexture(unitnum);
+ qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
+ }
+ if (unit->rgbscale != 1)
+ {
+ GL_ActiveTexture(unitnum);
+ qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (unit->rgbscale = 1));CHECKGLERROR
+ }
+ if (unit->alphascale != 1)
+ {
+ GL_ActiveTexture(unitnum);
+ qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, (unit->alphascale = 1));CHECKGLERROR
+ }
+ }
+ else
+ {
+ // normal GL texenv
+ if (unit->combinergb != GL_MODULATE)
+ {
+ unit->combinergb = GL_MODULATE;
+ GL_ActiveTexture(unitnum);
+ qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combinergb);CHECKGLERROR
+ }
+ }
+ }
+}
+
+void R_Mesh_Draw_ShowTris(int firstvertex, int numvertices, int numtriangles, const int *elements)
+{
+ CHECKGLERROR
+ qglBegin(GL_LINES);
+ for (;numtriangles;numtriangles--, elements += 3)
+ {
+ qglArrayElement(elements[0]);qglArrayElement(elements[1]);
+ qglArrayElement(elements[1]);qglArrayElement(elements[2]);
+ qglArrayElement(elements[2]);qglArrayElement(elements[0]);
+ }
+ qglEnd();
+ CHECKGLERROR
+}