}
}
+static void **drawbatch_buffer = NULL;
+static size_t drawbatch_buffer_size = 0;
+extern void GL_BindEBO(int bufferobject);
void RSurf_DrawBatch(void)
{
// sometimes a zero triangle surface (usually a degenerate patch) makes it
if (rsurface.batchmultidraw)
{
// issue multiple draws rather than copying index data
- int numsurfaces = rsurface.batchmultidrawnumsurfaces;
- const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
- int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
- for (i = 0;i < numsurfaces;)
+ const msurface_t **surfacelist;
+ int numsurfaces;
+ int drawcount;
+ void **firstoffset;
+ GLsizei *indcount;
+ int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle, idraw;
+ surfacelist = rsurface.batchmultidrawsurfacelist;
+ numsurfaces = rsurface.batchmultidrawnumsurfaces;
+ // count entries in batch
+ drawcount = 1;
+ for (k = 0, j = 1; j < numsurfaces; k = j, j++)
+ if (surfacelist[j] != surfacelist[k] + 1)
+ drawcount++;
+ {
+ size_t size;
+ size = drawcount * (sizeof(void*) + sizeof(GLsizei));
+ if(size > drawbatch_buffer_size) {
+ Mem_Free(drawbatch_buffer);
+ drawbatch_buffer = NULL;
+ }
+ if(!drawbatch_buffer) {
+ drawbatch_buffer_size = size < 128 ? 128 : size;
+ drawbatch_buffer = (void**)Mem_Alloc(r_main_mempool, drawbatch_buffer_size * (sizeof(void*) + sizeof(GLsizei)));
+ }
+ firstoffset = drawbatch_buffer;
+ indcount = (GLsizei*)(drawbatch_buffer + drawcount);
+ }
+ for (i = 0, idraw = 0;i < numsurfaces; idraw++)
{
+ assert(idraw < drawcount);
// combine consecutive surfaces as one draw
for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
if (surfacelist[j] != surfacelist[k] + 1)
endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
firsttriangle = surfacelist[i]->num_firsttriangle;
endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
- R_Mesh_Draw(firstvertex, endvertex - firstvertex, firsttriangle, endtriangle - firsttriangle, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
+ if(rsurface.batchelement3s_indexbuffer) {
+ firstoffset[idraw] = (void*)(rsurface.batchelement3s_bufferoffset + (firsttriangle * 3 * sizeof(GLushort)));
+ indcount[idraw] = (endtriangle - firsttriangle) * 3;
+ r_refdef.stats[r_stat_draws]++;
+ r_refdef.stats[r_stat_draws_vertices] += endvertex - firstvertex;
+ r_refdef.stats[r_stat_draws_elements] += endtriangle - firsttriangle;
+ } else if (rsurface.batchelement3i_indexbuffer) {
+ firstoffset[idraw] = (void*)(rsurface.batchelement3i_bufferoffset + (firsttriangle * 3 * sizeof(GLuint)));
+ indcount[idraw] = (endtriangle - firsttriangle) * 3;
+ r_refdef.stats[r_stat_draws]++;
+ r_refdef.stats[r_stat_draws_vertices] += endvertex - firstvertex;
+ r_refdef.stats[r_stat_draws_elements] += endtriangle - firsttriangle;
+ } else {
+ // fallback for dynamic surface and glDrawArray
+ R_Mesh_Draw(firstvertex, endvertex - firstvertex, firsttriangle, endtriangle - firsttriangle, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
+ }
i = j;
}
+
+ if (rsurface.batchelement3s_indexbuffer) {
+ CHECKGLERROR
+ GL_BindEBO(rsurface.batchelement3s_indexbuffer->bufferobject);
+ qglMultiDrawElements(GL_TRIANGLES, indcount, GL_UNSIGNED_SHORT, firstoffset, drawcount);
+ CHECKGLERROR
+ } else if (rsurface.batchelement3i_indexbuffer) {
+ CHECKGLERROR
+ GL_BindEBO(rsurface.batchelement3i_indexbuffer->bufferobject);
+ qglMultiDrawElements(GL_TRIANGLES, indcount, GL_UNSIGNED_INT, firstoffset, drawcount);
+ CHECKGLERROR
+ }
}
else
{
extern void (GLAPIENTRY *qglDrawBuffer)(GLenum mode);
extern void (GLAPIENTRY *qglDrawBuffers)(GLsizei n, const GLenum *bufs);
extern void (GLAPIENTRY *qglDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
+extern void (GLAPIENTRY *qglMultiDrawElements)(GLenum mode, const GLsizei *count, GLenum type, const GLvoid *indices, GLsizei drawcount);
extern void (GLAPIENTRY *qglEnable)(GLenum cap);
extern void (GLAPIENTRY *qglEnableVertexAttribArray)(GLuint index);
extern void (GLAPIENTRY *qglEndQuery)(GLenum target);
#define qglDrawBuffer glDrawBuffer
#define qglDrawBuffers glDrawBuffers
#define qglDrawElements glDrawElements
+#define qglMultiDrawElements glMultiDrawElements
#define qglEnable glEnable
#define qglEnableVertexAttribArray glEnableVertexAttribArray
#define qglEndQuery glEndQuery
void (GLAPIENTRY *qglDrawBuffer)(GLenum mode);
void (GLAPIENTRY *qglDrawBuffers)(GLsizei n, const GLenum *bufs);
void (GLAPIENTRY *qglDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
+void (GLAPIENTRY *qglMultiDrawElements)(GLenum mode, const GLsizei *count, GLenum type, const GLvoid *indices, GLsizei drawcount);
void (GLAPIENTRY *qglEnable)(GLenum cap);
void (GLAPIENTRY *qglEnableVertexAttribArray)(GLuint index);
void (GLAPIENTRY *qglEndQuery)(GLenum target);
{"core", "glDrawBuffer", (void **) &qglDrawBuffer},
{"core", "glDrawBuffers", (void **) &qglDrawBuffers},
{"core", "glDrawElements", (void **) &qglDrawElements},
+ {"core", "glMultiDrawElements", (void **) &qglMultiDrawElements},
{"core", "glEnable", (void **) &qglEnable},
{"core", "glEnableVertexAttribArray", (void **) &qglEnableVertexAttribArray},
{"core", "glEndQuery", (void **) &qglEndQuery},