#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.3"};
+cvar_t gl_mesh_vertex_array_range_writefrequency = {0, "gl_mesh_vertex_array_range_writefrequency", "1"};
+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"};
GLfloat *varray_color, *varray_buf_color;
GLfloat *varray_texcoord[MAX_TEXTUREUNITS], *varray_buf_texcoord[MAX_TEXTUREUNITS];
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_elements;
int mesh_maxelements = 3072;
varray_buf_elements = 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;
if (!gl_backend_mempool)
{
varray_buf_texcoord[i] = NULL;
}
+ 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_vertex)
- Mem_Free(varray_buf_vertex);
+ VID_FreeVertexArrays(varray_buf_vertex);
varray_buf_vertex = NULL;
- if (varray_buf_color)
- Mem_Free(varray_buf_color);
varray_buf_color = NULL;
- if (varray_buf_bcolor)
- Mem_Free(varray_buf_bcolor);
varray_buf_bcolor = NULL;
for (i = 0;i < MAX_TEXTUREUNITS;i++)
- {
- if (varray_buf_texcoord[i])
- Mem_Free(varray_buf_texcoord[i]);
varray_buf_texcoord[i] = NULL;
- }
- varray_buf_vertex = Mem_Alloc(gl_backend_mempool, mesh_maxverts * sizeof(GLfloat[4]));
- varray_buf_color = Mem_Alloc(gl_backend_mempool, mesh_maxverts * sizeof(GLfloat[4]));
- varray_buf_bcolor = Mem_Alloc(gl_backend_mempool, mesh_maxverts * sizeof(GLubyte[4]));
+ size = mesh_maxverts * (sizeof(GLfloat[4]) + sizeof(GLfloat[4]) + sizeof(GLfloat[4]) * backendunits + sizeof(GLubyte[4]));
+ varray_buf_vertex = 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_color = varray_buf_vertex + 4 * mesh_maxverts;
for (i = 0;i < backendunits;i++)
- varray_buf_texcoord[i] = Mem_Alloc(gl_backend_mempool, mesh_maxverts * sizeof(GLfloat[4]));
+ varray_buf_texcoord[i] = varray_buf_vertex + (i + 2) * 4 * mesh_maxverts;
for (;i < MAX_TEXTUREUNITS;i++)
varray_buf_texcoord[i] = NULL;
+ varray_buf_bcolor = (GLubyte *)(varray_buf_vertex + (backendunits + 2) * 4 * mesh_maxverts);
GL_Backend_AllocElementsArray();
+
+ if (gl_support_var)
+ {
+ CHECKGLERROR
+ qglVertexArrayRangeNV(size, varray_buf_vertex);
+ CHECKGLERROR
+ qglEnableClientState(GL_VERTEX_ARRAY_RANGE_NV);
+ CHECKGLERROR
+ }
}
void GL_Backend_FreeArrays(void)
{
int i;
- Mem_FreePool(&gl_backend_mempool);
+ if (gl_support_var)
+ {
+ CHECKGLERROR
+ qglDisableClientState(GL_VERTEX_ARRAY_RANGE_NV);
+ CHECKGLERROR
+ }
+
+ if (varray_buf_vertex)
+ VID_FreeVertexArrays(varray_buf_vertex);
varray_buf_vertex = NULL;
varray_buf_color = NULL;
varray_buf_bcolor = NULL;
for (i = 0;i < MAX_TEXTUREUNITS;i++)
varray_buf_texcoord[i] = NULL;
+ Mem_FreePool(&gl_backend_mempool);
+
varray_buf_elements = NULL;
}
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);
GL_Backend_FreeArrays();
}
-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);
-}
-
void GL_Backend_ResizeArrays(int numvertices)
{
Cvar_SetValueQuick(&gl_mesh_maxverts, numvertices);
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);
}
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;
varray_offset = varray_offsetnext;
if (varray_offset + numverts > mesh_maxverts)
- {
- //flush stuff here
varray_offset = 0;
- }
if (numverts > mesh_maxverts)
{
BACKENDACTIVECHECK
varray_offset = 0;
}
+ if (varray_offset == 0 && mesh_var)
+ {
+ CHECKGLERROR
+ qglFlushVertexArrayRangeNV();
+ CHECKGLERROR
+ }
+
// for debugging
- //varray_offset = rand() % (mesh_maxverts - numverts);
+ //if (!mesh_var)
+ // varray_offset = rand() % (mesh_maxverts - numverts);
varray_vertex = varray_buf_vertex + varray_offset * 4;
varray_color = varray_buf_color + varray_offset * 4;
{
int i;
BACKENDACTIVECHECK
+ if (mesh_var)
+ {
+ CHECKGLERROR
+ qglFlushVertexArrayRangeNV();
+ CHECKGLERROR
+ }
+ varray_offset = 0;
for (i = backendunits - 1;i >= 0;i--)
{
int gl_dot3arb = false;
// GL_SGIS_texture_edge_clamp
int gl_support_clamptoedge = false;
+// GL_NV_vertex_array_range
+int gl_support_var = false;
+// GL_NV_vertex_array_range2
+int gl_support_var2 = false;
// LordHavoc: if window is hidden, don't update screen
int vid_hidden = true;
void (GLAPIENTRY *qglLockArraysEXT) (GLint first, GLint count);
void (GLAPIENTRY *qglUnlockArraysEXT) (void);
+//GL_NV_vertex_array_range
+GLvoid *(GLAPIENTRY *qglAllocateMemoryNV)(GLsizei size, GLfloat readFrequency, GLfloat writeFrequency, GLfloat priority);
+GLvoid (GLAPIENTRY *qglFreeMemoryNV)(GLvoid *pointer);
+GLvoid (GLAPIENTRY *qglVertexArrayRangeNV)(GLsizei length, GLvoid *pointer);
+GLvoid (GLAPIENTRY *qglFlushVertexArrayRangeNV)(GLvoid);
// general GL functions
{NULL, NULL}
};
+static dllfunction_t glxvarfuncs[] =
+{
+ {"glXAllocateMemoryNV", (void **) &qglAllocateMemoryNV},
+ {"glXFreeMemoryNV", (void **) &qglFreeMemoryNV},
+ {"glVertexArrayRangeNV", (void **) &qglVertexArrayRangeNV},
+ {"glFlushVertexArrayRangeNV", (void **) &qglFlushVertexArrayRangeNV},
+ {NULL, NULL}
+};
+
+static dllfunction_t wglvarfuncs[] =
+{
+ {"wglAllocateMemoryNV", (void **) &qglAllocateMemoryNV},
+ {"wglFreeMemoryNV", (void **) &qglFreeMemoryNV},
+ {"glVertexArrayRangeNV", (void **) &qglVertexArrayRangeNV},
+ {"glFlushVertexArrayRangeNV", (void **) &qglFlushVertexArrayRangeNV},
+ {NULL, NULL}
+};
+
+
void VID_CheckExtensions(void)
{
gl_stencil = vid_stencil.integer;
gl_supportslockarrays = false;
gl_textureunits = 1;
gl_support_clamptoedge = false;
+ gl_support_var = false;
+ gl_support_var2 = false;
if (!GL_CheckExtension("OpenGL 1.1.0", opengl110funcs, NULL, false))
Sys_Error("OpenGL 1.1.0 functions not found\n");
gl_supportslockarrays = GL_CheckExtension("GL_EXT_compiled_vertex_array", compiledvertexarrayfuncs, "-nocva", false);
gl_support_clamptoedge = GL_CheckExtension("GL_EXT_texture_edge_clamp", NULL, "-noedgeclamp", false) || GL_CheckExtension("GL_SGIS_texture_edge_clamp", NULL, "-noedgeclamp", false);
+ if (!strcmp(gl_platform, "GLX"))
+ gl_support_var = GL_CheckExtension("GL_NV_vertex_array_range", glxvarfuncs, "-novar", false);
+ else if (!strcmp(gl_platform, "WGL"))
+ gl_support_var = GL_CheckExtension("GL_NV_vertex_array_range", wglvarfuncs, "-novar", false);
+ if (gl_support_var)
+ gl_support_var2 = GL_CheckExtension("GL_NV_vertex_array_range2", NULL, "-novar2", false);
+
// we don't care if it's an extension or not, they are identical functions, so keep it simple in the rendering code
if (qglDrawRangeElements == NULL)
qglDrawRangeElements = qglDrawRangeElementsEXT;
}
+int vid_vertexarrays_are_var = false;
+void *VID_AllocVertexArrays(mempool_t *pool, int size, int fast, float readfrequency, float writefrequency, float priority)
+{
+ void *m;
+ vid_vertexarrays_are_var = false;
+ if (fast && qglAllocateMemoryNV)
+ {
+ CHECKGLERROR
+ m = qglAllocateMemoryNV(size, readfrequency, writefrequency, priority);
+ CHECKGLERROR
+ if (m)
+ {
+ vid_vertexarrays_are_var = true;
+ return m;
+ }
+ }
+ return Mem_Alloc(pool, size);
+}
+
+void VID_FreeVertexArrays(void *pointer)
+{
+ if (vid_vertexarrays_are_var)
+ {
+ CHECKGLERROR
+ qglFreeMemoryNV(pointer);
+ CHECKGLERROR
+ }
+ else
+ Mem_Free(pointer);
+ vid_vertexarrays_are_var = false;
+}
+
void Force_CenterView_f (void)
{
cl.viewangles[PITCH] = 0;
VID_CloseSystems();
VID_Shutdown();
}
+