X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=gl_backend.c;h=a7e0dd46f6882c5d0f9cc47c6aeb58003656d6b7;hb=5e48e932b1ae931fd143537781e80bb832a9bdea;hp=e6790294e0f0d5c8f32188f407496d5456745007;hpb=a26c29e7adac278a87059324e40868823c752680;p=xonotic%2Fdarkplaces.git diff --git a/gl_backend.c b/gl_backend.c index e6790294..a7e0dd46 100644 --- a/gl_backend.c +++ b/gl_backend.c @@ -12,7 +12,8 @@ cvar_t r_render = {0, "r_render", "1", "enables rendering calls (you want this o cvar_t r_waterwarp = {CVAR_SAVE, "r_waterwarp", "1", "warp view while underwater"}; 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 = {0, "gl_lockarrays", "0", "enables use of glLockArraysEXT, may cause glitches with some broken drivers, and may be slower than normal"}; +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; @@ -73,7 +74,6 @@ void SCR_ScreenShot_f (void); static matrix4x4_t backend_viewmatrix; static matrix4x4_t backend_modelmatrix; static matrix4x4_t backend_modelviewmatrix; -static matrix4x4_t backend_glmodelviewmatrix; static matrix4x4_t backend_projectmatrix; static unsigned int backendunits, backendimageunits, backendarrayunits, backendactive; @@ -158,7 +158,7 @@ static void gl_backend_start(void) Con_Printf("glDrawRangeElements detected (max vertices %i, max indices %i)\n", gl_maxdrawrangeelementsvertices, gl_maxdrawrangeelementsindices); } - backendunits = min(MAX_TEXTUREUNITS, gl_textureunits); + backendunits = bound(1, gl_textureunits, MAX_TEXTUREUNITS); backendimageunits = backendunits; backendarrayunits = backendunits; if (gl_support_fragment_shader) @@ -169,6 +169,8 @@ static void gl_backend_start(void) qglGetIntegerv(GL_MAX_TEXTURE_COORDS_ARB, (int *)&backendarrayunits); CHECKGLERROR Con_Printf("GLSL shader support detected: texture units = %i texenv, %i image, %i array\n", backendunits, backendimageunits, backendarrayunits); + backendimageunits = bound(1, backendimageunits, MAX_TEXTUREUNITS); + backendarrayunits = bound(1, backendarrayunits, MAX_TEXTUREUNITS); } else if (backendunits > 1) Con_Printf("multitexture detected: texture units = %i\n", backendunits); @@ -226,6 +228,7 @@ void gl_backend_init(void) 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 @@ -245,7 +248,7 @@ void GL_SetupView_Orientation_Identity (void) 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); @@ -342,6 +345,8 @@ gltextureunit_t; static struct gl_state_s { + int cullface; + int cullfaceenable; int blendfunc1; int blendfunc2; int blend; @@ -468,6 +473,8 @@ void GL_Backend_ResetState(void) gl_state.lockrange_count = 0; gl_state.pointer_vertex = NULL; gl_state.pointer_color = NULL; + gl_state.cullface = GL_FRONT; // quake is backwards, this culls back faces + gl_state.cullfaceenable = true; CHECKGLERROR @@ -476,7 +483,7 @@ void GL_Backend_ResetState(void) qglDisable(GL_ALPHA_TEST);CHECKGLERROR qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR qglDisable(GL_BLEND);CHECKGLERROR - qglCullFace(GL_FRONT);CHECKGLERROR + qglCullFace(gl_state.cullface);CHECKGLERROR qglEnable(GL_CULL_FACE);CHECKGLERROR qglDepthFunc(GL_LEQUAL);CHECKGLERROR qglEnable(GL_DEPTH_TEST);CHECKGLERROR @@ -584,6 +591,32 @@ void GL_DepthTest(int state) } } +void GL_CullFace(int state) +{ + CHECKGLERROR + if (state != GL_NONE) + { + if (!gl_state.cullfaceenable) + { + gl_state.cullfaceenable = true; + qglEnable(GL_CULL_FACE);CHECKGLERROR + } + if (gl_state.cullface != state) + { + 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_AlphaTest(int state) { if (gl_state.alphatest != state) @@ -628,6 +661,11 @@ void GL_Color(float cr, float cg, float cb, float ca) 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) @@ -699,108 +737,73 @@ void R_Mesh_Start(void) 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) @@ -831,7 +834,7 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int numtriangles, const int * 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 @@ -1034,11 +1037,12 @@ void R_Mesh_Matrix(const matrix4x4_t *matrix) { if (memcmp(matrix, &backend_modelmatrix, sizeof(matrix4x4_t))) { + double glmatrix[16]; backend_modelmatrix = *matrix; Matrix4x4_Concat(&backend_modelviewmatrix, &backend_viewmatrix, matrix); - Matrix4x4_Transpose(&backend_glmodelviewmatrix, &backend_modelviewmatrix); + Matrix4x4_ToArrayDoubleGL(&backend_modelviewmatrix, glmatrix); CHECKGLERROR - qglLoadMatrixf(&backend_glmodelviewmatrix.m[0][0]);CHECKGLERROR + qglLoadMatrixd(glmatrix);CHECKGLERROR } } @@ -1511,14 +1515,14 @@ void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix) // texmatrix specified, check if it is different if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t))) { - matrix4x4_t tempmatrix; + double glmatrix[16]; unit->texmatrixenabled = true; unit->matrix = *matrix; CHECKGLERROR - Matrix4x4_Transpose(&tempmatrix, &unit->matrix); + Matrix4x4_ToArrayDoubleGL(&unit->matrix, glmatrix); qglMatrixMode(GL_TEXTURE);CHECKGLERROR GL_ActiveTexture(unitnum); - qglLoadMatrixf(&tempmatrix.m[0][0]);CHECKGLERROR + qglLoadMatrixd(glmatrix);CHECKGLERROR qglMatrixMode(GL_MODELVIEW);CHECKGLERROR } }