cvar_t gl_polyblend = {CVAR_SAVE, "gl_polyblend", "1", "tints view while underwater, hurt, etc"};
cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1", "enables OpenGL dithering (16bit looks bad with this off)"};
cvar_t gl_lockarrays = {0, "gl_lockarrays", "1", "enables use of glLockArraysEXT, may cause glitches with some broken drivers"};
+cvar_t gl_lockarrays_minimumvertices = {0, "gl_lockarrays_minimumvertices", "1", "minimum number of vertices required for use of glLockArraysEXT, setting this too low may reduce performance"};
int gl_maxdrawrangeelementsvertices;
int gl_maxdrawrangeelementsindices;
Cvar_RegisterVariable(&gl_polyblend);
Cvar_RegisterVariable(&gl_dither);
Cvar_RegisterVariable(&gl_lockarrays);
+ Cvar_RegisterVariable(&gl_lockarrays_minimumvertices);
Cvar_RegisterVariable(&gl_paranoid);
Cvar_RegisterVariable(&gl_printcheckerror);
#ifdef NORENDER
memset(&backend_modelmatrix, 0, sizeof(backend_modelmatrix));
}
-void GL_SetupView_Orientation_FromEntity(matrix4x4_t *matrix)
+void GL_SetupView_Orientation_FromEntity(const matrix4x4_t *matrix)
{
matrix4x4_t tempmatrix, basematrix;
Matrix4x4_Invert_Simple(&tempmatrix, matrix);
void GL_CullFace(int state)
{
- if (gl_state.cullface != state)
+ CHECKGLERROR
+ if (state != GL_NONE)
{
- CHECKGLERROR
- if (state != GL_NONE)
+ if (!gl_state.cullfaceenable)
{
- if (!gl_state.cullfaceenable)
- {
- gl_state.cullfaceenable = true;
- qglEnable(GL_CULL_FACE);CHECKGLERROR
- }
- if (gl_state.cullface != state)
- {
- gl_state.cullface = state;
- qglCullFace(state);CHECKGLERROR
- }
+ gl_state.cullfaceenable = true;
+ qglEnable(GL_CULL_FACE);CHECKGLERROR
}
- else
+ if (gl_state.cullface != state)
{
- if (gl_state.cullfaceenable)
- {
- gl_state.cullfaceenable = false;
- qglDisable(GL_CULL_FACE);CHECKGLERROR
- }
+ gl_state.cullface = state;
+ qglCullFace(gl_state.cullface);CHECKGLERROR
+ }
+ }
+ else
+ {
+ if (gl_state.cullfaceenable)
+ {
+ gl_state.cullfaceenable = false;
+ qglDisable(GL_CULL_FACE);CHECKGLERROR
}
}
}
void GL_LockArrays(int first, int count)
{
+ if (count < gl_lockarrays_minimumvertices.integer)
+ {
+ first = 0;
+ count = 0;
+ }
if (gl_state.lockrange_count != count || gl_state.lockrange_first != first)
{
if (gl_state.lockrange_count)
GL_Backend_ResetState();
}
-unsigned int GL_Backend_CompileProgram(int vertexstrings_count, const char **vertexstrings_list, int fragmentstrings_count, const char **fragmentstrings_list)
+qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
{
- GLint vertexshadercompiled, fragmentshadercompiled, programlinked;
- GLuint vertexshaderobject, fragmentshaderobject, programobject = 0;
+ int shaderobject;
+ int shadercompiled;
char compilelog[MAX_INPUTLINE];
+ shaderobject = qglCreateShaderObjectARB(shadertypeenum);CHECKGLERROR
+ if (!shaderobject)
+ return false;
+ qglShaderSourceARB(shaderobject, numstrings, strings, NULL);CHECKGLERROR
+ qglCompileShaderARB(shaderobject);CHECKGLERROR
+ qglGetObjectParameterivARB(shaderobject, GL_OBJECT_COMPILE_STATUS_ARB, &shadercompiled);CHECKGLERROR
+ qglGetInfoLogARB(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
+ if (compilelog[0])
+ Con_DPrintf("%s shader compile log:\n%s\n", shadertype, compilelog);
+ if (!shadercompiled)
+ {
+ qglDeleteObjectARB(shaderobject);CHECKGLERROR
+ return false;
+ }
+ qglAttachObjectARB(programobject, shaderobject);CHECKGLERROR
+ qglDeleteObjectARB(shaderobject);CHECKGLERROR
+ return true;
+}
+
+unsigned int GL_Backend_CompileProgram(int vertexstrings_count, const char **vertexstrings_list, int geometrystrings_count, const char **geometrystrings_list, int fragmentstrings_count, const char **fragmentstrings_list)
+{
+ GLint programlinked;
+ GLuint programobject = 0;
+ char linklog[MAX_INPUTLINE];
CHECKGLERROR
programobject = qglCreateProgramObjectARB();CHECKGLERROR
if (!programobject)
return 0;
- if (developer.integer >= 100)
- {
- int i;
- Con_Printf("Compiling shader:\n");
- if (vertexstrings_count)
- {
- Con_Printf("------ VERTEX SHADER ------\n");
- for (i = 0;i < vertexstrings_count;i++)
- Con_Print(vertexstrings_list[i]);
- Con_Print("\n");
- }
- if (fragmentstrings_count)
- {
- Con_Printf("------ FRAGMENT SHADER ------\n");
- for (i = 0;i < fragmentstrings_count;i++)
- Con_Print(fragmentstrings_list[i]);
- Con_Print("\n");
- }
- }
+ if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER_ARB, "vertex", vertexstrings_count, vertexstrings_list))
+ goto cleanup;
- if (vertexstrings_count)
- {
- vertexshaderobject = qglCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);CHECKGLERROR
- if (!vertexshaderobject)
- {
- qglDeleteObjectARB(programobject);
- CHECKGLERROR
- return 0;
- }
- qglShaderSourceARB(vertexshaderobject, vertexstrings_count, vertexstrings_list, NULL);CHECKGLERROR
- qglCompileShaderARB(vertexshaderobject);CHECKGLERROR
- qglGetObjectParameterivARB(vertexshaderobject, GL_OBJECT_COMPILE_STATUS_ARB, &vertexshadercompiled);CHECKGLERROR
- qglGetInfoLogARB(vertexshaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
- if (compilelog[0])
- Con_DPrintf("vertex shader compile log:\n%s\n", compilelog);
- if (!vertexshadercompiled)
- {
- qglDeleteObjectARB(programobject);CHECKGLERROR
- qglDeleteObjectARB(vertexshaderobject);CHECKGLERROR
- return 0;
- }
- qglAttachObjectARB(programobject, vertexshaderobject);CHECKGLERROR
- qglDeleteObjectARB(vertexshaderobject);CHECKGLERROR
- }
+#ifdef GL_GEOMETRY_SHADER_ARB
+ if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER_ARB, "geometry", geometrystrings_count, geometrystrings_list))
+ goto cleanup;
+#endif
- if (fragmentstrings_count)
- {
- fragmentshaderobject = qglCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);CHECKGLERROR
- if (!fragmentshaderobject)
- {
- qglDeleteObjectARB(programobject);CHECKGLERROR
- return 0;
- }
- qglShaderSourceARB(fragmentshaderobject, fragmentstrings_count, fragmentstrings_list, NULL);CHECKGLERROR
- qglCompileShaderARB(fragmentshaderobject);CHECKGLERROR
- qglGetObjectParameterivARB(fragmentshaderobject, GL_OBJECT_COMPILE_STATUS_ARB, &fragmentshadercompiled);CHECKGLERROR
- qglGetInfoLogARB(fragmentshaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
- if (compilelog[0])
- Con_DPrintf("fragment shader compile log:\n%s\n", compilelog);
- if (!fragmentshadercompiled)
- {
- qglDeleteObjectARB(programobject);CHECKGLERROR
- qglDeleteObjectARB(fragmentshaderobject);CHECKGLERROR
- return 0;
- }
- qglAttachObjectARB(programobject, fragmentshaderobject);CHECKGLERROR
- qglDeleteObjectARB(fragmentshaderobject);CHECKGLERROR
- }
+ if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER_ARB, "fragment", fragmentstrings_count, fragmentstrings_list))
+ goto cleanup;
qglLinkProgramARB(programobject);CHECKGLERROR
qglGetObjectParameterivARB(programobject, GL_OBJECT_LINK_STATUS_ARB, &programlinked);CHECKGLERROR
- qglGetInfoLogARB(programobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
- if (compilelog[0])
+ qglGetInfoLogARB(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
+ if (linklog[0])
{
- Con_DPrintf("program link log:\n%s\n", compilelog);
+ Con_DPrintf("program link log:\n%s\n", linklog);
// software vertex shader is ok but software fragment shader is WAY
// too slow, fail program if so.
// 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"))
+ if (strstr(linklog, "fragment shader will run in software"))
programlinked = false;
}
if (!programlinked)
- {
- qglDeleteObjectARB(programobject);CHECKGLERROR
- return 0;
- }
- CHECKGLERROR
+ goto cleanup;
return programobject;
+cleanup:
+ qglDeleteObjectARB(programobject);CHECKGLERROR
+ return 0;
}
void GL_Backend_FreeProgram(unsigned int prog)
unsigned int numelements = numtriangles * 3;
if (numvertices < 3 || numtriangles < 1)
{
- Con_Printf("R_Mesh_Draw(%d, %d, %d, %08p);\n", firstvertex, numvertices, numtriangles, elements);
+ Con_Printf("R_Mesh_Draw(%d, %d, %d, %8p);\n", firstvertex, numvertices, numtriangles, elements);
return;
}
CHECKGLERROR