X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=gl_backend.c;h=a454952718a9ef02d1558f51aa6255b76380b155;hb=17837f58260f8fa29420cba9b95ee10f74612335;hp=9ce7459d2c5de3376f994ca4626ee63d49bec9b9;hpb=877a36e05a774846346d0d4fe7e19d823488a668;p=xonotic%2Fdarkplaces.git diff --git a/gl_backend.c b/gl_backend.c index 9ce7459d..a4549527 100644 --- a/gl_backend.c +++ b/gl_backend.c @@ -2,9 +2,14 @@ #include "quakedef.h" #include "image.h" -cvar_t gl_mesh_maxverts = {0, "gl_mesh_maxverts", "1024"}; +cvar_t gl_mesh_maxverts = {0, "gl_mesh_maxverts", "21760"}; cvar_t gl_mesh_floatcolors = {0, "gl_mesh_floatcolors", "1"}; cvar_t gl_mesh_drawrangeelements = {0, "gl_mesh_drawrangeelements", "1"}; +cvar_t gl_mesh_vertex_array_range = {0, "gl_mesh_vertex_array_range", "0"}; +cvar_t gl_mesh_vertex_array_range_readfrequency = {0, "gl_mesh_vertex_array_range_readfrequency", "0.2"}; +cvar_t gl_mesh_vertex_array_range_writefrequency = {0, "gl_mesh_vertex_array_range_writefrequency", "0.2"}; +cvar_t gl_mesh_vertex_array_range_priority = {0, "gl_mesh_vertex_array_range_priority", "0.7"}; +cvar_t gl_delayfinish = {CVAR_SAVE, "gl_delayfinish", "0"}; cvar_t r_render = {0, "r_render", "1"}; cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1"}; // whether or not to use dithering @@ -51,7 +56,7 @@ void GL_PrintError(int errornumber, char *filename, int linenumber) break; #endif #ifdef GL_TABLE_TOO_LARGE - case GL_TABLE_TOO_LARGE: + case GL_TABLE_TOO_LARGE: Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber); break; #endif @@ -71,10 +76,19 @@ void SCR_ScreenShot_f (void); // these are externally accessible int r_lightmapscalebit; float r_colorscale; -float *varray_vertex; -float *varray_color; -float *varray_texcoord[MAX_TEXTUREUNITS]; +GLfloat *varray_vertex3f, *varray_buf_vertex3f; +GLfloat *varray_color4f, *varray_buf_color4f; +GLfloat *varray_texcoord3f[MAX_TEXTUREUNITS], *varray_buf_texcoord3f[MAX_TEXTUREUNITS]; +GLfloat *varray_texcoord2f[MAX_TEXTUREUNITS], *varray_buf_texcoord2f[MAX_TEXTUREUNITS]; +static qbyte *varray_color4b, *varray_buf_color4b; int mesh_maxverts; +int mesh_var; +float mesh_var_readfrequency; +float mesh_var_writefrequency; +float mesh_var_priority; +int varray_offset = 0, varray_offsetnext = 0; +GLuint *varray_buf_elements3i; +int mesh_maxelements = 3072; static matrix4x4_t backend_viewmatrix; static matrix4x4_t backend_modelmatrix; @@ -83,7 +97,6 @@ static matrix4x4_t backend_glmodelviewmatrix; static matrix4x4_t backend_projectmatrix; static int backendunits, backendactive; -static qbyte *varray_bcolor; static mempool_t *gl_backend_mempool; /* @@ -103,51 +116,133 @@ A0B, 01B, B1C, 12C, C2D, 23D, D3E, 34E *elements++ = i + row + 1; */ +void GL_Backend_AllocElementsArray(void) +{ + if (varray_buf_elements3i) + Mem_Free(varray_buf_elements3i); + varray_buf_elements3i = Mem_Alloc(gl_backend_mempool, mesh_maxelements * sizeof(GLuint)); +} + +void GL_Backend_FreeElementArray(void) +{ + if (varray_buf_elements3i) + Mem_Free(varray_buf_elements3i); + varray_buf_elements3i = NULL; +} + +void GL_Backend_CheckCvars(void) +{ + // 21760 is (65536 / 3) rounded off to a multiple of 128 + if (gl_mesh_maxverts.integer < 1024) + Cvar_SetValueQuick(&gl_mesh_maxverts, 1024); + if (gl_mesh_maxverts.integer > 21760) + Cvar_SetValueQuick(&gl_mesh_maxverts, 21760); + if (gl_mesh_vertex_array_range.integer && !gl_support_var) + Cvar_SetValueQuick(&gl_mesh_vertex_array_range, 0); + if (gl_mesh_vertex_array_range_readfrequency.value < 0) + Cvar_SetValueQuick(&gl_mesh_vertex_array_range_readfrequency, 0); + if (gl_mesh_vertex_array_range_readfrequency.value > 1) + Cvar_SetValueQuick(&gl_mesh_vertex_array_range_readfrequency, 1); + if (gl_mesh_vertex_array_range_writefrequency.value < 0) + Cvar_SetValueQuick(&gl_mesh_vertex_array_range_writefrequency, 0); + if (gl_mesh_vertex_array_range_writefrequency.value > 1) + Cvar_SetValueQuick(&gl_mesh_vertex_array_range_writefrequency, 1); + if (gl_mesh_vertex_array_range_priority.value < 0) + Cvar_SetValueQuick(&gl_mesh_vertex_array_range_priority, 0); + if (gl_mesh_vertex_array_range_priority.value > 1) + Cvar_SetValueQuick(&gl_mesh_vertex_array_range_priority, 1); +} + int polygonelements[768]; void GL_Backend_AllocArrays(void) { - int i; + int i, size; + qbyte *data; - for (i = 0;i < POLYGONELEMENTS_MAXPOINTS - 2;i++) + if (!gl_backend_mempool) { - polygonelements[i * 3 + 0] = 0; - polygonelements[i * 3 + 1] = i + 1; - polygonelements[i * 3 + 2] = i + 2; + gl_backend_mempool = Mem_AllocPool("GL_Backend"); + varray_buf_vertex3f = NULL; + varray_buf_color4f = NULL; + varray_buf_color4b = NULL; + varray_buf_elements3i = NULL; + for (i = 0;i < MAX_TEXTUREUNITS;i++) + varray_buf_texcoord3f[i] = varray_buf_texcoord2f[i] = NULL; } - if (!gl_backend_mempool) - gl_backend_mempool = Mem_AllocPool("GL_Backend"); + mesh_maxverts = gl_mesh_maxverts.integer; + mesh_var = gl_mesh_vertex_array_range.integer; + mesh_var_readfrequency = gl_mesh_vertex_array_range_readfrequency.value; + mesh_var_writefrequency = gl_mesh_vertex_array_range_writefrequency.value; + mesh_var_priority = gl_mesh_vertex_array_range_priority.value; + + if (varray_buf_vertex3f) + VID_FreeVertexArrays(varray_buf_vertex3f); + varray_buf_vertex3f = NULL; + varray_buf_color4f = NULL; + varray_buf_color4b = NULL; + for (i = 0;i < MAX_TEXTUREUNITS;i++) + varray_buf_texcoord3f[i] = varray_buf_texcoord2f[i] = NULL; - varray_vertex = Mem_Alloc(gl_backend_mempool, mesh_maxverts * sizeof(float[4])); - varray_color = Mem_Alloc(gl_backend_mempool, mesh_maxverts * sizeof(float[4])); - varray_bcolor = Mem_Alloc(gl_backend_mempool, mesh_maxverts * sizeof(qbyte[4])); + size = mesh_maxverts * (sizeof(float[3]) + sizeof(float[4]) + sizeof(qbyte[4]) + (sizeof(float[3]) + sizeof(float[2])) * backendunits); + data = VID_AllocVertexArrays(gl_backend_mempool, size, gl_mesh_vertex_array_range.integer, gl_mesh_vertex_array_range_readfrequency.value, gl_mesh_vertex_array_range_writefrequency.value, gl_mesh_vertex_array_range_priority.value); + varray_buf_vertex3f = (void *)data;data += sizeof(float[3]) * mesh_maxverts; + varray_buf_color4f = (void *)data;data += sizeof(float[4]) * mesh_maxverts; for (i = 0;i < backendunits;i++) - varray_texcoord[i] = Mem_Alloc(gl_backend_mempool, mesh_maxverts * sizeof(float[4])); + { + varray_buf_texcoord3f[i] = (void *)data;data += sizeof(float[3]) * mesh_maxverts; + varray_buf_texcoord2f[i] = (void *)data;data += sizeof(float[2]) * mesh_maxverts; + } for (;i < MAX_TEXTUREUNITS;i++) - varray_texcoord[i] = NULL; + varray_buf_texcoord3f[i] = varray_buf_texcoord2f[i] = NULL; + varray_buf_color4b = (void *)data;data += sizeof(qbyte[4]) * mesh_maxverts; + + GL_Backend_AllocElementsArray(); + + if (gl_support_var) + { + CHECKGLERROR + qglVertexArrayRangeNV(size, varray_buf_vertex3f); + CHECKGLERROR + qglEnableClientState(GL_VERTEX_ARRAY_RANGE_NV); + CHECKGLERROR + } } -void GL_Backend_FreeArrays(int resizingbuffers) +void GL_Backend_FreeArrays(void) { int i; - if (resizingbuffers) - Mem_EmptyPool(gl_backend_mempool); - else - Mem_FreePool(&gl_backend_mempool); - varray_vertex = NULL; - varray_color = NULL; - varray_bcolor = NULL; + + if (gl_support_var) + { + CHECKGLERROR + qglDisableClientState(GL_VERTEX_ARRAY_RANGE_NV); + CHECKGLERROR + } + + if (varray_buf_vertex3f) + VID_FreeVertexArrays(varray_buf_vertex3f); + varray_buf_vertex3f = NULL; + varray_buf_color4f = NULL; + varray_buf_color4b = NULL; for (i = 0;i < MAX_TEXTUREUNITS;i++) - varray_texcoord[i] = NULL; + varray_buf_texcoord3f[i] = varray_buf_texcoord2f[i] = NULL; + varray_buf_elements3i = NULL; + + Mem_FreePool(&gl_backend_mempool); } static void gl_backend_start(void) { + GL_Backend_CheckCvars(); + Con_Printf("OpenGL Backend started with gl_mesh_maxverts %i\n", gl_mesh_maxverts.integer); if (qglDrawRangeElements != NULL) { + CHECKGLERROR qglGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &gl_maxdrawrangeelementsvertices); + CHECKGLERROR qglGetIntegerv(GL_MAX_ELEMENTS_INDICES, &gl_maxdrawrangeelementsindices); CHECKGLERROR Con_Printf("glDrawRangeElements detected (max vertices %i, max indices %i)\n", gl_maxdrawrangeelementsvertices, gl_maxdrawrangeelementsindices); @@ -172,24 +267,14 @@ static void gl_backend_shutdown(void) Con_Printf("OpenGL Backend shutting down\n"); - GL_Backend_FreeArrays(false); + GL_Backend_FreeArrays(); } -void GL_Backend_CheckCvars(void) +void GL_Backend_ResizeArrays(int numvertices) { - // 21760 is (65536 / 3) rounded off to a multiple of 128 - if (gl_mesh_maxverts.integer < 1024) - Cvar_SetValueQuick(&gl_mesh_maxverts, 1024); - if (gl_mesh_maxverts.integer > 21760) - Cvar_SetValueQuick(&gl_mesh_maxverts, 21760); -} - -void GL_Backend_ResizeArrays(int numtriangles) -{ - Cvar_SetValueQuick(&gl_mesh_maxverts, numtriangles); + Cvar_SetValueQuick(&gl_mesh_maxverts, numvertices); GL_Backend_CheckCvars(); mesh_maxverts = gl_mesh_maxverts.integer; - GL_Backend_FreeArrays(true); GL_Backend_AllocArrays(); } @@ -199,9 +284,19 @@ static void gl_backend_newmap(void) void gl_backend_init(void) { + int i; + + for (i = 0;i < POLYGONELEMENTS_MAXPOINTS - 2;i++) + { + polygonelements[i * 3 + 0] = 0; + polygonelements[i * 3 + 1] = i + 1; + polygonelements[i * 3 + 2] = i + 2; + } + Cvar_RegisterVariable(&r_render); Cvar_RegisterVariable(&gl_dither); Cvar_RegisterVariable(&gl_lockarrays); + Cvar_RegisterVariable(&gl_delayfinish); #ifdef NORENDER Cvar_SetValue("r_render", 0); #endif @@ -209,7 +304,10 @@ void gl_backend_init(void) Cvar_RegisterVariable(&gl_mesh_maxverts); Cvar_RegisterVariable(&gl_mesh_floatcolors); Cvar_RegisterVariable(&gl_mesh_drawrangeelements); - GL_Backend_CheckCvars(); + Cvar_RegisterVariable(&gl_mesh_vertex_array_range); + Cvar_RegisterVariable(&gl_mesh_vertex_array_range_readfrequency); + Cvar_RegisterVariable(&gl_mesh_vertex_array_range_writefrequency); + Cvar_RegisterVariable(&gl_mesh_vertex_array_range_priority); R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap); } @@ -249,7 +347,7 @@ void GL_SetupView_Mode_Perspective (double fovx, double fovy, double zNear, doub // set up viewpoint qglMatrixMode(GL_PROJECTION);CHECKGLERROR - qglLoadIdentity ();CHECKGLERROR + qglLoadIdentity();CHECKGLERROR // pyramid slopes xmax = zNear * tan(fovx * M_PI / 360.0); ymax = zNear * tan(fovy * M_PI / 360.0); @@ -261,14 +359,14 @@ void GL_SetupView_Mode_Perspective (double fovx, double fovy, double zNear, doub void GL_SetupView_Mode_PerspectiveInfiniteFarClip (double fovx, double fovy, double zNear) { - double nudge, m[16]; + float nudge, m[16]; if (!r_render.integer) return; // set up viewpoint qglMatrixMode(GL_PROJECTION);CHECKGLERROR - qglLoadIdentity ();CHECKGLERROR + qglLoadIdentity();CHECKGLERROR // set view pyramid nudge = 1.0 - 1.0 / (1<<23); m[ 0] = 1.0 / tan(fovx * M_PI / 360.0); @@ -287,7 +385,7 @@ void GL_SetupView_Mode_PerspectiveInfiniteFarClip (double fovx, double fovy, dou m[13] = 0; m[14] = -2 * zNear * nudge; m[15] = 0; - qglLoadMatrixd(m); + qglLoadMatrixf(m); qglMatrixMode(GL_MODELVIEW);CHECKGLERROR GL_SetupView_Orientation_Identity(); backend_projectmatrix.m[0][0] = m[0]; @@ -315,7 +413,7 @@ void GL_SetupView_Mode_Ortho (double x1, double y1, double x2, double y2, double // set up viewpoint qglMatrixMode(GL_PROJECTION);CHECKGLERROR - qglLoadIdentity ();CHECKGLERROR + qglLoadIdentity();CHECKGLERROR qglOrtho(x1, x2, y2, y1, zNear, zFar); qglMatrixMode(GL_MODELVIEW);CHECKGLERROR GL_SetupView_Orientation_Identity(); @@ -323,8 +421,8 @@ void GL_SetupView_Mode_Ortho (double x1, double y1, double x2, double y2, double typedef struct gltextureunit_s { - unsigned int t1d, t2d, t3d, tcubemap; - unsigned int arrayenabled; + int t1d, t2d, t3d, tcubemap; + int arrayenabled, arrayis3d; float rgbscale, alphascale; int combinergb, combinealpha; // FIXME: add more combine stuff @@ -365,15 +463,9 @@ void GL_SetupTextureState(void) unit->combinergb = GL_MODULATE; unit->combinealpha = GL_MODULATE; unit->arrayenabled = false; + unit->arrayis3d = false; qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR - if (gl_texture3d || gl_texturecubemap) - { - qglTexCoordPointer(3, GL_FLOAT, sizeof(float[4]), varray_texcoord[i]);CHECKGLERROR - } - else - { - qglTexCoordPointer(2, GL_FLOAT, sizeof(float[4]), varray_texcoord[i]);CHECKGLERROR - } + qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), varray_buf_texcoord2f[i]);CHECKGLERROR qglDisable(GL_TEXTURE_1D);CHECKGLERROR qglDisable(GL_TEXTURE_2D);CHECKGLERROR if (gl_texture3d) @@ -430,15 +522,15 @@ void GL_Backend_ResetState(void) qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR qglDisable(GL_BLEND);CHECKGLERROR qglDepthMask(gl_state.depthmask);CHECKGLERROR - qglVertexPointer(3, GL_FLOAT, sizeof(float[4]), varray_vertex);CHECKGLERROR + qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), varray_buf_vertex3f);CHECKGLERROR qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR if (gl_mesh_floatcolors.integer) { - qglColorPointer(4, GL_FLOAT, sizeof(float[4]), varray_color);CHECKGLERROR + qglColorPointer(4, GL_FLOAT, sizeof(float[4]), varray_buf_color4f);CHECKGLERROR } else { - qglColorPointer(4, GL_UNSIGNED_BYTE, sizeof(qbyte[4]), varray_bcolor);CHECKGLERROR + qglColorPointer(4, GL_UNSIGNED_BYTE, sizeof(qbyte[4]), varray_buf_color4b);CHECKGLERROR } GL_Color(1, 1, 1, 1); @@ -484,10 +576,22 @@ void R_Mesh_Start(void) CHECKGLERROR GL_Backend_CheckCvars(); - if (mesh_maxverts != gl_mesh_maxverts.integer) + if (mesh_maxverts != gl_mesh_maxverts.integer + || mesh_var != gl_mesh_vertex_array_range.integer + || mesh_var_readfrequency != gl_mesh_vertex_array_range_readfrequency.value + || mesh_var_writefrequency != gl_mesh_vertex_array_range_writefrequency.value + || mesh_var_priority != gl_mesh_vertex_array_range_priority.value) GL_Backend_ResizeArrays(gl_mesh_maxverts.integer); GL_Backend_ResetState(); + + if (mesh_var) + { + CHECKGLERROR + qglFlushVertexArrayRangeNV(); + CHECKGLERROR + } + varray_offset = 0; } int gl_backend_rebindtextures; @@ -500,12 +604,12 @@ void GL_ConvertColorsFloatToByte(int numverts) // (or a union) volatile int *icolor; volatile float *fcolor; - qbyte *bcolor; + GLubyte *bcolor; total = numverts * 4; // shift float to have 8bit fraction at base of number - fcolor = varray_color; + fcolor = varray_buf_color4f; for (i = 0;i < total;) { fcolor[i ] += 32768.0f; @@ -516,70 +620,122 @@ void GL_ConvertColorsFloatToByte(int numverts) } // then read as integer and kill float bits... - icolor = (int *)varray_color; - bcolor = varray_bcolor; + icolor = (int *)varray_buf_color4f; + bcolor = varray_buf_color4b; for (i = 0;i < total;) { - k = icolor[i ] & 0x7FFFFF;if (k > 255) k = 255;bcolor[i ] = (qbyte) k; - k = icolor[i + 1] & 0x7FFFFF;if (k > 255) k = 255;bcolor[i + 1] = (qbyte) k; - k = icolor[i + 2] & 0x7FFFFF;if (k > 255) k = 255;bcolor[i + 2] = (qbyte) k; - k = icolor[i + 3] & 0x7FFFFF;if (k > 255) k = 255;bcolor[i + 3] = (qbyte) k; + k = icolor[i ] & 0x7FFFFF;if (k > 255) k = 255;bcolor[i ] = (GLubyte) k; + k = icolor[i + 1] & 0x7FFFFF;if (k > 255) k = 255;bcolor[i + 1] = (GLubyte) k; + k = icolor[i + 2] & 0x7FFFFF;if (k > 255) k = 255;bcolor[i + 2] = (GLubyte) k; + k = icolor[i + 3] & 0x7FFFFF;if (k > 255) k = 255;bcolor[i + 3] = (GLubyte) k; i += 4; } } -void GL_DrawRangeElements(int firstvert, int endvert, int indexcount, const int *index) +/* +// enlarges geometry buffers if they are too small +void _R_Mesh_ResizeCheck(int numverts) { - int arraylocked = false; - c_meshs++; - c_meshelements += indexcount; - if (indexcount == 0 || endvert == firstvert) - { - Con_Printf("GL_DrawRangeElements(%d, %d, %d, %08p);\n", firstvert, endvert, indexcount, index); - return; - } - if (gl_supportslockarrays && gl_lockarrays.integer) - { - qglLockArraysEXT(firstvert, endvert - firstvert); - CHECKGLERROR - arraylocked = true; - } - if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL) - qglDrawRangeElements(GL_TRIANGLES, firstvert, endvert, indexcount, GL_UNSIGNED_INT, (const GLuint *) index); - else - qglDrawElements(GL_TRIANGLES, indexcount, GL_UNSIGNED_INT, (const GLuint *) index); - CHECKGLERROR - if (arraylocked) + if (numverts > mesh_maxverts) { - qglUnlockArraysEXT(); - CHECKGLERROR - arraylocked = false; + BACKENDACTIVECHECK + GL_Backend_ResizeArrays(numverts + 100); + GL_Backend_ResetState(); } } +*/ -// enlarges geometry buffers if they are too small -void _R_Mesh_ResizeCheck(int numverts) +void GL_Backend_RenumberElements(int numelements, const int *in, int offset) { + int i; + for (i = 0;i < numelements;i++) + varray_buf_elements3i[i] = in[i] + offset; +} + +// gets geometry space for a mesh +void R_Mesh_GetSpace(int numverts) +{ + int i; + + varray_offset = varray_offsetnext; + if (varray_offset + numverts > mesh_maxverts) + varray_offset = 0; if (numverts > mesh_maxverts) { BACKENDACTIVECHECK GL_Backend_ResizeArrays(numverts + 100); GL_Backend_ResetState(); + varray_offset = 0; + } + + if (varray_offset == 0 && mesh_var) + { + CHECKGLERROR + qglFlushVertexArrayRangeNV(); + CHECKGLERROR + } + + // for debugging + //if (!mesh_var) + // varray_offset = rand() % (mesh_maxverts - numverts); + + varray_vertex3f = varray_buf_vertex3f + varray_offset * 3; + varray_color4f = varray_buf_color4f + varray_offset * 4; + varray_color4b = varray_buf_color4b + varray_offset * 4; + for (i = 0;i < backendunits;i++) + { + varray_texcoord3f[i] = varray_buf_texcoord3f[i] + varray_offset * 3; + varray_texcoord2f[i] = varray_buf_texcoord2f[i] + varray_offset * 2; } + + varray_offsetnext = varray_offset + numverts; } -// renders the mesh +// renders the current mesh void R_Mesh_Draw(int numverts, int numtriangles, const int *elements) { - BACKENDACTIVECHECK - - CHECKGLERROR - + int numelements; + if (numtriangles == 0 || numverts == 0) + { + Con_Printf("R_Mesh_Draw(%d, %d, %08p);\n", numverts, numtriangles, elements); + return; + } + numelements = numtriangles * 3; + if (mesh_maxelements < numelements) + { + mesh_maxelements = numelements; + GL_Backend_AllocElementsArray(); + } + GL_Backend_RenumberElements(numelements, elements, varray_offset); + c_meshs++; + c_meshelements += numelements; if (gl_state.colorarray && !gl_mesh_floatcolors.integer) GL_ConvertColorsFloatToByte(numverts); - if (!r_render.integer) - return; - GL_DrawRangeElements(0, numverts, numtriangles * 3, elements); + if (r_render.integer) + { + if (gl_supportslockarrays && gl_lockarrays.integer) + { + qglLockArraysEXT(varray_offset, numverts); + CHECKGLERROR + if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL) + { + qglDrawRangeElements(GL_TRIANGLES, varray_offset, varray_offset + numverts, numelements, GL_UNSIGNED_INT, (const GLuint *) varray_buf_elements3i); + CHECKGLERROR + } + else + { + qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (const GLuint *) varray_buf_elements3i); + CHECKGLERROR + } + qglUnlockArraysEXT(); + CHECKGLERROR + } + else + { + qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (const GLuint *) varray_buf_elements3i); + CHECKGLERROR + } + } } // restores backend state, used when done with 3D rendering @@ -587,6 +743,13 @@ void R_Mesh_Finish(void) { int i; BACKENDACTIVECHECK + if (mesh_var) + { + CHECKGLERROR + qglFlushVertexArrayRangeNV(); + CHECKGLERROR + } + varray_offset = 0; for (i = backendunits - 1;i >= 0;i--) { @@ -701,12 +864,38 @@ void R_Mesh_TextureState(const rmeshstate_t *m) unit = gl_state.units + i; if (unit->t1d != m->tex1d[i] || unit->t2d != m->tex[i] || unit->t3d != m->tex3d[i] || unit->tcubemap != m->texcubemap[i]) { - if (gl_state.unit != i) + if (m->tex3d[i] || m->texcubemap[i]) { - qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR + if (!unit->arrayis3d) + { + unit->arrayis3d = true; + if (gl_state.clientunit != i) + { + qglClientActiveTexture(GL_TEXTURE0_ARB + (gl_state.clientunit = i));CHECKGLERROR + } + qglTexCoordPointer(3, GL_FLOAT, sizeof(float[3]), varray_buf_texcoord3f[i]); + } + if (!unit->arrayenabled) + { + unit->arrayenabled = true; + if (gl_state.clientunit != i) + { + qglClientActiveTexture(GL_TEXTURE0_ARB + (gl_state.clientunit = i));CHECKGLERROR + } + qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR + } } - if (m->tex1d[i] || m->tex[i] || m->tex3d[i] || m->texcubemap[i]) + else if (m->tex1d[i] || m->tex[i]) { + if (unit->arrayis3d) + { + unit->arrayis3d = false; + if (gl_state.clientunit != i) + { + qglClientActiveTexture(GL_TEXTURE0_ARB + (gl_state.clientunit = i));CHECKGLERROR + } + qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), varray_buf_texcoord2f[i]); + } if (!unit->arrayenabled) { unit->arrayenabled = true; @@ -729,34 +918,12 @@ void R_Mesh_TextureState(const rmeshstate_t *m) qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR } } - combinergb = m->texcombinergb[i]; - combinealpha = m->texcombinealpha[i]; - if (!combinergb) - combinergb = GL_MODULATE; - if (!combinealpha) - combinealpha = GL_MODULATE; - if (unit->combinergb != combinergb) - { - unit->combinergb = combinergb; - if (gl_combine.integer) - { - qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR - } - else - { - qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combinergb);CHECKGLERROR - } - } - if (unit->combinealpha != combinealpha) + if (unit->t1d != m->tex1d[i]) { - unit->combinealpha = combinealpha; - if (gl_combine.integer) + if (gl_state.unit != i) { - qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR + qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR } - } - if (unit->t1d != m->tex1d[i]) - { if (m->tex1d[i]) { if (unit->t1d == 0) @@ -771,6 +938,10 @@ void R_Mesh_TextureState(const rmeshstate_t *m) } if (unit->t2d != m->tex[i]) { + if (gl_state.unit != i) + { + qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR + } if (m->tex[i]) { if (unit->t2d == 0) @@ -785,6 +956,10 @@ void R_Mesh_TextureState(const rmeshstate_t *m) } if (unit->t3d != m->tex3d[i]) { + if (gl_state.unit != i) + { + qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR + } if (m->tex3d[i]) { if (unit->t3d == 0) @@ -799,6 +974,10 @@ void R_Mesh_TextureState(const rmeshstate_t *m) } if (unit->tcubemap != m->texcubemap[i]) { + if (gl_state.unit != i) + { + qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR + } if (m->texcubemap[i]) { if (unit->tcubemap == 0) @@ -812,6 +991,40 @@ void R_Mesh_TextureState(const rmeshstate_t *m) qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, (unit->tcubemap = m->texcubemap[i]));CHECKGLERROR } } + combinergb = m->texcombinergb[i]; + if (!combinergb) + combinergb = GL_MODULATE; + if (unit->combinergb != combinergb) + { + if (gl_state.unit != i) + { + qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR + } + unit->combinergb = combinergb; + if (gl_combine.integer) + { + qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR + } + else + { + qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combinergb);CHECKGLERROR + } + } + combinealpha = m->texcombinealpha[i]; + if (!combinealpha) + combinealpha = GL_MODULATE; + if (unit->combinealpha != combinealpha) + { + if (gl_state.unit != i) + { + qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR + } + unit->combinealpha = combinealpha; + if (gl_combine.integer) + { + qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR + } + } scale = max(m->texrgbscale[i], 1); if (gl_state.units[i].rgbscale != scale) { @@ -850,7 +1063,7 @@ void R_Mesh_State(const rmeshstate_t *m) qboolean SCR_ScreenShot(char *filename, int x, int y, int width, int height) { qboolean ret; - int i; + int i, j; qbyte *buffer; if (!r_render.integer) @@ -862,8 +1075,13 @@ qboolean SCR_ScreenShot(char *filename, int x, int y, int width, int height) // LordHavoc: compensate for v_overbrightbits when using hardware gamma if (v_hwgamma.integer) + { for (i = 0;i < width * height * 3;i++) - buffer[i] <<= v_overbrightbits.integer; + { + j = buffer[i] << v_overbrightbits.integer; + buffer[i] = (qbyte) (bound(0, j, 255)); + } + } ret = Image_WriteTGARGB_preflipped(filename, width, height, buffer); @@ -882,7 +1100,10 @@ void R_ClearScreen(void) qglClearDepth(1);CHECKGLERROR if (gl_stencil) { - qglClearStencil(0);CHECKGLERROR + // LordHavoc: we use a stencil centered around 128 instead of 0, + // to avoid clamping interfering with strange shadow volume + // drawing orders + qglClearStencil(128);CHECKGLERROR } // clear the screen qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | (gl_stencil ? GL_STENCIL_BUFFER_BIT : 0));CHECKGLERROR @@ -908,9 +1129,12 @@ text to the screen. */ void SCR_UpdateScreen (void) { - VID_Finish (); + if (gl_delayfinish.integer) + { + VID_Finish (); - R_TimeReport("finish"); + R_TimeReport("finish"); + } if (r_textureunits.integer > gl_textureunits) Cvar_SetValueQuick(&r_textureunits, gl_textureunits); @@ -940,8 +1164,68 @@ void SCR_UpdateScreen (void) // draw 2D stuff R_DrawQueue(); - // tell driver to commit it's partially full geometry queue to the rendering queue - // (this doesn't wait for the commands themselves to complete) - qglFlush(); + if (gl_delayfinish.integer) + { + // tell driver to commit it's partially full geometry queue to the rendering queue + // (this doesn't wait for the commands themselves to complete) + qglFlush(); + } + else + { + VID_Finish (); + + R_TimeReport("finish"); + } +} + +// utility functions + +void R_Mesh_CopyVertex3f(const float *vertex3f, int numverts) +{ + if (mesh_var) + { + float *out = varray_vertex3f; + while (--numverts) + { + *out++ = *vertex3f++; + *out++ = *vertex3f++; + *out++ = *vertex3f++; + } + } + else + memcpy(varray_vertex3f, vertex3f, numverts * sizeof(float[3])); +} + +void R_Mesh_CopyTexCoord2f(int tmu, const float *texcoord2f, int numverts) +{ + if (mesh_var) + { + float *out = varray_texcoord2f[tmu]; + while (--numverts) + { + *out++ = *texcoord2f++; + *out++ = *texcoord2f++; + } + } + else + memcpy(varray_texcoord2f[tmu], texcoord2f, numverts * sizeof(float[2])); } +void R_Mesh_CopyColor4f(const float *color4f, int numverts) +{ + if (mesh_var) + { + float *out = varray_color4f; + while (--numverts) + { + *out++ = *color4f++; + *out++ = *color4f++; + *out++ = *color4f++; + *out++ = *color4f++; + } + } + else + memcpy(varray_color4f, color4f, numverts * sizeof(float[4])); +} + +