+ qglEnable(GL_DEPTH_TEST);CHECKGLERROR
+ }
+ else
+ {
+ qglDisable(GL_DEPTH_TEST);CHECKGLERROR
+ }
+ }
+}
+
+void GL_ColorMask(int r, int g, int b, int a)
+{
+ int state = r*8 + g*4 + b*2 + a*1;
+ if (gl_state.colormask != state)
+ {
+ if (r_showtrispass)
+ return;
+ gl_state.colormask = state;
+ qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
+ }
+}
+
+void GL_Color(float cr, float cg, float cb, float ca)
+{
+ if (gl_state.pointer_color || gl_state.color4f[0] != cr || gl_state.color4f[1] != cg || gl_state.color4f[2] != cb || gl_state.color4f[3] != ca)
+ {
+ if (r_showtrispass)
+ return;
+ gl_state.color4f[0] = cr;
+ gl_state.color4f[1] = cg;
+ gl_state.color4f[2] = cb;
+ gl_state.color4f[3] = ca;
+ CHECKGLERROR
+ qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
+ CHECKGLERROR
+ }
+}
+
+void GL_ShowTrisColor(float cr, float cg, float cb, float ca)
+{
+ if (!r_showtrispass)
+ return;
+ r_showtrispass = false;
+ GL_Color(cr * r_showtris.value, cg * r_showtris.value, cb * r_showtris.value, ca);
+ r_showtrispass = true;
+}
+
+
+void GL_LockArrays(int first, int count)
+{
+ if (gl_state.lockrange_count != count || gl_state.lockrange_first != first)
+ {
+ if (gl_state.lockrange_count)
+ {
+ gl_state.lockrange_count = 0;
+ CHECKGLERROR
+ qglUnlockArraysEXT();
+ CHECKGLERROR
+ }
+ if (count && gl_supportslockarrays && gl_lockarrays.integer && r_render.integer)
+ {
+ gl_state.lockrange_first = first;
+ gl_state.lockrange_count = count;
+ CHECKGLERROR
+ qglLockArraysEXT(first, count);
+ CHECKGLERROR
+ }
+ }
+}
+
+void GL_Scissor (int x, int y, int width, int height)
+{
+ CHECKGLERROR
+ qglScissor(x, vid.realheight - (y + height),width,height);
+ CHECKGLERROR
+}
+
+void GL_ScissorTest(int state)
+{
+ if(gl_state.scissortest == state)
+ return;
+
+ CHECKGLERROR
+ if((gl_state.scissortest = state))
+ qglEnable(GL_SCISSOR_TEST);
+ else
+ qglDisable(GL_SCISSOR_TEST);
+ CHECKGLERROR
+}
+
+void GL_Clear(int mask)
+{
+ if (r_showtrispass)
+ return;
+ qglClear(mask);CHECKGLERROR
+}
+
+void GL_TransformToScreen(const vec4_t in, vec4_t out)
+{
+ vec4_t temp;
+ float iw;
+ Matrix4x4_Transform4 (&backend_viewmatrix, in, temp);
+ Matrix4x4_Transform4 (&backend_projectmatrix, temp, out);
+ iw = 1.0f / out[3];
+ out[0] = r_view_x + (out[0] * iw + 1.0f) * r_view_width * 0.5f;
+ out[1] = r_view_y + (out[1] * iw + 1.0f) * r_view_height * 0.5f;
+ out[2] = r_view_z + (out[2] * iw + 1.0f) * r_view_depth * 0.5f;
+}
+
+// called at beginning of frame
+void R_Mesh_Start(void)
+{
+ BACKENDACTIVECHECK
+ CHECKGLERROR
+ GL_Backend_ResetState();
+}
+
+unsigned int GL_Backend_CompileProgram(int vertexstrings_count, const char **vertexstrings_list, int fragmentstrings_count, const char **fragmentstrings_list)
+{
+ GLint vertexshadercompiled, fragmentshadercompiled, programlinked;
+ GLuint vertexshaderobject, fragmentshaderobject, programobject = 0;
+ char compilelog[4096];
+ CHECKGLERROR
+
+ programobject = qglCreateProgramObjectARB();
+ CHECKGLERROR
+ if (!programobject)
+ return 0;
+
+ if (vertexstrings_count)
+ {
+ CHECKGLERROR
+ vertexshaderobject = qglCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
+ if (!vertexshaderobject)
+ {
+ qglDeleteObjectARB(programobject);
+ CHECKGLERROR
+ return 0;
+ }
+ qglShaderSourceARB(vertexshaderobject, vertexstrings_count, vertexstrings_list, NULL);
+ qglCompileShaderARB(vertexshaderobject);
+ CHECKGLERROR
+ qglGetObjectParameterivARB(vertexshaderobject, GL_OBJECT_COMPILE_STATUS_ARB, &vertexshadercompiled);
+ qglGetInfoLogARB(vertexshaderobject, sizeof(compilelog), NULL, compilelog);
+ if (compilelog[0])
+ Con_Printf("vertex shader compile log:\n%s\n", compilelog);
+ if (!vertexshadercompiled)
+ {
+ qglDeleteObjectARB(programobject);
+ qglDeleteObjectARB(vertexshaderobject);
+ CHECKGLERROR
+ return 0;
+ }
+ qglAttachObjectARB(programobject, vertexshaderobject);
+ qglDeleteObjectARB(vertexshaderobject);
+ CHECKGLERROR
+ }
+
+ if (fragmentstrings_count)
+ {
+ CHECKGLERROR
+ fragmentshaderobject = qglCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
+ if (!fragmentshaderobject)
+ {
+ qglDeleteObjectARB(programobject);
+ CHECKGLERROR
+ return 0;
+ }
+ qglShaderSourceARB(fragmentshaderobject, fragmentstrings_count, fragmentstrings_list, NULL);
+ qglCompileShaderARB(fragmentshaderobject);
+ CHECKGLERROR
+ qglGetObjectParameterivARB(fragmentshaderobject, GL_OBJECT_COMPILE_STATUS_ARB, &fragmentshadercompiled);
+ qglGetInfoLogARB(fragmentshaderobject, sizeof(compilelog), NULL, compilelog);
+ if (compilelog[0])
+ Con_Printf("fragment shader compile log:\n%s\n", compilelog);
+ if (!fragmentshadercompiled)
+ {
+ qglDeleteObjectARB(programobject);
+ qglDeleteObjectARB(fragmentshaderobject);
+ CHECKGLERROR
+ return 0;
+ }
+ qglAttachObjectARB(programobject, fragmentshaderobject);
+ qglDeleteObjectARB(fragmentshaderobject);
+ CHECKGLERROR
+ }
+
+ qglLinkProgramARB(programobject);
+ CHECKGLERROR
+ qglGetObjectParameterivARB(programobject, GL_OBJECT_LINK_STATUS_ARB, &programlinked);
+ qglGetInfoLogARB(programobject, sizeof(compilelog), NULL, compilelog);
+ if (compilelog[0])
+ {
+ Con_Printf("program link log:\n%s\n", compilelog);
+ // software vertex shader is ok but software fragment shader is WAY
+ // too slow, fail program if so.
+ // NOTE: this string might be ATI specific, but that's ok because the
+ // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
+ // software fragment shader due to low instruction and dependent
+ // texture limits.
+ if (strstr(compilelog, "fragment shader will run in software"))
+ programlinked = false;
+ }
+ CHECKGLERROR
+ if (!programlinked)
+ {
+ qglDeleteObjectARB(programobject);
+ return 0;
+ }
+ CHECKGLERROR
+ return programobject;
+}
+
+void GL_Backend_FreeProgram(unsigned int prog)
+{
+ CHECKGLERROR
+ qglDeleteObjectARB(prog);
+ CHECKGLERROR
+}
+
+int gl_backend_rebindtextures;
+
+void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
+{
+ int i;
+ if (offset)
+ {
+ for (i = 0;i < count;i++)
+ *out++ = *in++ + offset;
+ }
+ else
+ memcpy(out, in, sizeof(*out) * count);
+}
+
+// renders triangles using vertices from the active arrays
+int paranoidblah = 0;
+void R_Mesh_Draw(int firstvertex, int numvertices, int numtriangles, const int *elements)
+{
+ unsigned int numelements = numtriangles * 3;
+ if (numvertices < 3 || numtriangles < 1)
+ {
+ Con_Printf("R_Mesh_Draw(%d, %d, %d, %08p);\n", firstvertex, numvertices, numtriangles, elements);
+ return;
+ }
+ //CHECKGLERROR
+ if (r_showtrispass)
+ {
+ R_Mesh_Draw_ShowTris(firstvertex, numvertices, numtriangles, elements);
+ return;
+ }
+ c_meshs++;
+ c_meshelements += numelements;
+ if (gl_paranoid.integer)
+ {
+ unsigned int i, j, size;
+ const int *p;
+ if (!qglIsEnabled(GL_VERTEX_ARRAY))
+ Con_Print("R_Mesh_Draw: vertex array not enabled\n");
+ for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
+ paranoidblah += *p;
+ if (gl_state.pointer_color)
+ {
+ if (!qglIsEnabled(GL_COLOR_ARRAY))
+ Con_Print("R_Mesh_Draw: color array set but not enabled\n");
+ for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
+ paranoidblah += *p;
+ }
+ for (i = 0;i < backendarrayunits;i++)
+ {
+ if (gl_state.units[i].arrayenabled)
+ {
+ GL_ClientActiveTexture(i);
+ if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
+ Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
+ for (j = 0, size = numvertices * gl_state.units[i].arraycomponents, p = (int *)((float *)gl_state.units[i].pointer_texcoord + firstvertex * gl_state.units[i].arraycomponents);j < size;j++, p++)
+ paranoidblah += *p;