summaryrefslogtreecommitdiff
path: root/src/mesa/vbo
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2009-08-27 10:09:24 -0700
committerEric Anholt <eric@anholt.net>2009-09-08 15:12:20 -0700
commit92d7ed8a20d4a018ce5324e6537ae7b478b9e5bf (patch)
treedb04f9d7c60b1cd174c93fbe112f00058c85e092 /src/mesa/vbo
parentec9e7295800aff0f04815de736127101f770033f (diff)
mesa: Add support for ARB_draw_elements_base_vertex.
Diffstat (limited to 'src/mesa/vbo')
-rw-r--r--src/mesa/vbo/vbo.h1
-rw-r--r--src/mesa/vbo/vbo_exec_array.c131
-rw-r--r--src/mesa/vbo/vbo_rebase.c15
-rw-r--r--src/mesa/vbo/vbo_save_api.c36
-rw-r--r--src/mesa/vbo/vbo_split.c8
-rw-r--r--src/mesa/vbo/vbo_split_copy.c52
6 files changed, 200 insertions, 43 deletions
diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h
index 5986e93576..b24ecfd7cd 100644
--- a/src/mesa/vbo/vbo.h
+++ b/src/mesa/vbo/vbo.h
@@ -44,6 +44,7 @@ struct _mesa_prim {
GLuint start;
GLuint count;
+ GLint basevertex;
};
/* Would like to call this a "vbo_index_buffer", but this would be
diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c
index 12911f5750..b9550d6106 100644
--- a/src/mesa/vbo/vbo_exec_array.c
+++ b/src/mesa/vbo/vbo_exec_array.c
@@ -181,7 +181,7 @@ unmap_array_buffer(GLcontext *ctx, struct gl_client_array *array)
*/
static void
check_draw_elements_data(GLcontext *ctx, GLsizei count, GLenum elemType,
- const void *elements)
+ const void *elements, GLint basevertex)
{
struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
const void *elemMap;
@@ -518,6 +518,7 @@ vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)
prim[0].start = start;
prim[0].count = count;
prim[0].indexed = 0;
+ prim[0].basevertex = 0;
vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL,
GL_TRUE, start, start + count - 1 );
@@ -592,7 +593,8 @@ vbo_validated_drawrangeelements(GLcontext *ctx, GLenum mode,
GLboolean index_bounds_valid,
GLuint start, GLuint end,
GLsizei count, GLenum type,
- const GLvoid *indices)
+ const GLvoid *indices,
+ GLint basevertex)
{
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
@@ -626,6 +628,7 @@ vbo_validated_drawrangeelements(GLcontext *ctx, GLenum mode,
prim[0].start = 0;
prim[0].count = count;
prim[0].indexed = 1;
+ prim[0].basevertex = basevertex;
/* Need to give special consideration to rendering a range of
* indices starting somewhere above zero. Typically the
@@ -663,23 +666,25 @@ vbo_validated_drawrangeelements(GLcontext *ctx, GLenum mode,
}
static void GLAPIENTRY
-vbo_exec_DrawRangeElements(GLenum mode,
- GLuint start, GLuint end,
- GLsizei count, GLenum type, const GLvoid *indices)
+vbo_exec_DrawRangeElementsBaseVertex(GLenum mode,
+ GLuint start, GLuint end,
+ GLsizei count, GLenum type,
+ const GLvoid *indices,
+ GLint basevertex)
{
GET_CURRENT_CONTEXT(ctx);
if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count,
- type, indices ))
+ type, indices, basevertex ))
return;
if (end >= ctx->Array.ArrayObj->_MaxElement) {
/* the max element is out of bounds of one or more enabled arrays */
- _mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, count %d, "
- "type 0x%x, indices=%p)\n"
+ _mesa_warning(ctx, "glDraw[Range]Elements{,BaseVertex}(start %u, end %u, "
+ "count %d, type 0x%x, indices=%p, base=%d)\n"
"\tindex=%u is out of bounds (max=%u) "
"Element Buffer %u (size %d)",
- start, end, count, type, indices, end,
+ start, end, count, type, indices, end, basevertex,
ctx->Array.ArrayObj->_MaxElement - 1,
ctx->Array.ElementArrayBufferObj->Name,
ctx->Array.ElementArrayBufferObj->Size);
@@ -692,10 +697,12 @@ vbo_exec_DrawRangeElements(GLenum mode,
return;
}
else if (0) {
- _mesa_printf("glDraw[Range]Elements"
- "(start %u, end %u, type 0x%x, count %d) ElemBuf %u\n",
+ _mesa_printf("glDraw[Range]Elements{,BaseVertex}"
+ "(start %u, end %u, type 0x%x, count %d) ElemBuf %u, "
+ "base %d\n",
start, end, type, count,
- ctx->Array.ElementArrayBufferObj->Name);
+ ctx->Array.ElementArrayBufferObj->Name,
+ basevertex);
}
#if 0
@@ -705,7 +712,17 @@ vbo_exec_DrawRangeElements(GLenum mode,
#endif
vbo_validated_drawrangeelements(ctx, mode, GL_TRUE, start, end,
- count, type, indices);
+ count, type, indices, basevertex);
+}
+
+static void GLAPIENTRY
+vbo_exec_DrawRangeElements(GLenum mode,
+ GLuint start, GLuint end,
+ GLsizei count, GLenum type,
+ const GLvoid *indices)
+{
+ vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
+ indices, 0);
}
@@ -715,18 +732,33 @@ vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type,
{
GET_CURRENT_CONTEXT(ctx);
- if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices ))
+ if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 0 ))
+ return;
+
+ vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
+ count, type, indices, 0);
+}
+
+static void GLAPIENTRY
+vbo_exec_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices, GLint basevertex)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices,
+ basevertex ))
return;
vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
- count, type, indices);
+ count, type, indices, basevertex);
}
/* Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements */
static void
vbo_validated_multidrawelements(GLcontext *ctx, GLenum mode,
const GLsizei *count, GLenum type,
- const GLvoid **indices, GLsizei primcount)
+ const GLvoid **indices, GLsizei primcount,
+ const GLint *basevertex)
{
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
@@ -820,6 +852,10 @@ vbo_validated_multidrawelements(GLcontext *ctx, GLenum mode,
prim[i].start = ((uintptr_t)indices[i] - min_index_ptr) / index_type_size;
prim[i].count = count[i];
prim[i].indexed = 1;
+ if (basevertex != NULL)
+ prim[i].basevertex = basevertex[i];
+ else
+ prim[i].basevertex = 0;
}
vbo->draw_prims(ctx, exec->array.inputs, prim, primcount, &ib,
@@ -840,6 +876,10 @@ vbo_validated_multidrawelements(GLcontext *ctx, GLenum mode,
prim[0].start = 0;
prim[0].count = count[i];
prim[0].indexed = 1;
+ if (basevertex != NULL)
+ prim[0].basevertex = basevertex[i];
+ else
+ prim[0].basevertex = 0;
}
vbo->draw_prims(ctx, exec->array.inputs, prim, 1, &ib,
@@ -860,13 +900,36 @@ vbo_exec_MultiDrawElements(GLenum mode,
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
for (i = 0; i < primcount; i++) {
- if (!_mesa_validate_DrawElements( ctx, mode, count[i], type, indices[i] ))
+ if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i],
+ 0))
return;
}
- vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount);
+ vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
+ NULL);
}
+static void GLAPIENTRY
+vbo_exec_MultiDrawElementsBaseVertex(GLenum mode,
+ const GLsizei *count, GLenum type,
+ const GLvoid **indices,
+ GLsizei primcount,
+ const GLsizei *basevertex)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ for (i = 0; i < primcount; i++) {
+ if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i],
+ basevertex[i]))
+ return;
+ }
+
+ vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
+ basevertex);
+}
/***********************************************************************
@@ -881,11 +944,17 @@ vbo_exec_array_init( struct vbo_exec_context *exec )
exec->vtxfmt.DrawElements = vbo_exec_DrawElements;
exec->vtxfmt.DrawRangeElements = vbo_exec_DrawRangeElements;
exec->vtxfmt.MultiDrawElementsEXT = vbo_exec_MultiDrawElements;
+ exec->vtxfmt.DrawElementsBaseVertex = vbo_exec_DrawElementsBaseVertex;
+ exec->vtxfmt.DrawRangeElementsBaseVertex = vbo_exec_DrawRangeElementsBaseVertex;
+ exec->vtxfmt.MultiDrawElementsBaseVertex = vbo_exec_MultiDrawElementsBaseVertex;
#else
exec->vtxfmt.DrawArrays = _mesa_noop_DrawArrays;
exec->vtxfmt.DrawElements = _mesa_noop_DrawElements;
exec->vtxfmt.DrawRangeElements = _mesa_noop_DrawRangeElements;
exec->vtxfmt.MultiDrawElementsEXT = _mesa_noop_MultiDrawElements;
+ exec->vtxfmt.DrawElementsBaseVertex = _mesa_noop_DrawElementsBaseVertex;
+ exec->vtxfmt.DrawRangeElementsBaseVertex = _mesa_noop_DrawRangeElementsBaseVertex;
+ exec->vtxfmt.MultiDrawElementsBaseVertex = _mesa_noop_MultiDrawElementsBaseVertex;
#endif
}
@@ -913,6 +982,13 @@ _mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
vbo_exec_DrawElements(mode, count, type, indices);
}
+void GLAPIENTRY
+_mesa_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices, GLint basevertex)
+{
+ vbo_exec_DrawElementsBaseVertex(mode, count, type, indices, basevertex);
+}
+
/* This API entrypoint is not ordinarily used */
void GLAPIENTRY
@@ -922,6 +998,15 @@ _mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count,
vbo_exec_DrawRangeElements(mode, start, end, count, type, indices);
}
+void GLAPIENTRY
+_mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end,
+ GLsizei count, GLenum type,
+ const GLvoid *indices, GLint basevertex)
+{
+ vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
+ indices, basevertex);
+}
+
/* GL_EXT_multi_draw_arrays */
void GLAPIENTRY
_mesa_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type,
@@ -929,3 +1014,13 @@ _mesa_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type,
{
vbo_exec_MultiDrawElements(mode, count, type, indices, primcount);
}
+
+void GLAPIENTRY
+_mesa_MultiDrawElementsBaseVertex(GLenum mode,
+ const GLsizei *count, GLenum type,
+ const GLvoid **indices, GLsizei primcount,
+ const GLint *basevertex)
+{
+ vbo_exec_MultiDrawElementsBaseVertex(mode, count, type, indices,
+ primcount, basevertex);
+}
diff --git a/src/mesa/vbo/vbo_rebase.c b/src/mesa/vbo/vbo_rebase.c
index 3bf7ef580f..799a25fc1c 100644
--- a/src/mesa/vbo/vbo_rebase.c
+++ b/src/mesa/vbo/vbo_rebase.c
@@ -126,7 +126,20 @@ void vbo_rebase_prims( GLcontext *ctx,
if (0)
_mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
- if (ib) {
+
+ if (ib && ctx->Extensions.ARB_draw_elements_base_vertex) {
+ /* If we can just tell the hardware or the TNL to interpret our
+ * indices with a different base, do so.
+ */
+ tmp_prims = (struct _mesa_prim *)_mesa_malloc(sizeof(*prim) * nr_prims);
+
+ for (i = 0; i < nr_prims; i++) {
+ tmp_prims[i] = prim[i];
+ tmp_prims[i].basevertex -= min_index;
+ }
+
+ prim = tmp_prims;
+ } else if (ib) {
/* Unfortunately need to adjust each index individually.
*/
GLboolean map_ib = ib->obj->Name && !ib->obj->Pointer;
diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c
index 1771510d84..41cd21d04b 100644
--- a/src/mesa/vbo/vbo_save_api.c
+++ b/src/mesa/vbo/vbo_save_api.c
@@ -826,6 +826,33 @@ static void GLAPIENTRY _save_DrawRangeElements(GLenum mode,
_mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawRangeElements" );
}
+static void GLAPIENTRY _save_DrawElementsBaseVertex(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLint basevertex)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ (void) mode; (void) count; (void) type; (void) indices; (void)basevertex;
+
+ _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawElements" );
+}
+
+static void GLAPIENTRY _save_DrawRangeElementsBaseVertex(GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLint basevertex)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ (void) mode; (void) start; (void) end; (void) count; (void) type;
+ (void) indices; (void)basevertex;
+
+ _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawRangeElements" );
+}
+
static void GLAPIENTRY _save_DrawArrays(GLenum mode, GLint start, GLsizei count)
{
GET_CURRENT_CONTEXT(ctx);
@@ -907,7 +934,7 @@ static void GLAPIENTRY _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum
GET_CURRENT_CONTEXT(ctx);
GLint i;
- if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices ))
+ if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 0 ))
return;
_ae_map_vbos( ctx );
@@ -948,7 +975,7 @@ static void GLAPIENTRY _save_OBE_DrawRangeElements(GLenum mode,
GET_CURRENT_CONTEXT(ctx);
if (_mesa_validate_DrawRangeElements( ctx, mode,
start, end,
- count, type, indices ))
+ count, type, indices, 0 ))
_save_OBE_DrawElements( mode, count, type, indices );
}
@@ -1039,9 +1066,11 @@ static void _save_vtxfmt_init( GLcontext *ctx )
vfmt->DrawArrays = _save_DrawArrays;
vfmt->DrawElements = _save_DrawElements;
vfmt->DrawRangeElements = _save_DrawRangeElements;
+ vfmt->DrawElementsBaseVertex = _save_DrawElementsBaseVertex;
+ vfmt->DrawRangeElementsBaseVertex = _save_DrawRangeElementsBaseVertex;
/* Loops back into vfmt->DrawElements */
vfmt->MultiDrawElementsEXT = _mesa_noop_MultiDrawElements;
-
+ vfmt->MultiDrawElementsBaseVertex = _mesa_noop_MultiDrawElementsBaseVertex;
}
@@ -1233,6 +1262,7 @@ void vbo_save_api_init( struct vbo_save_context *save )
ctx->ListState.ListVtxfmt.DrawRangeElements = _save_OBE_DrawRangeElements;
/* loops back into _save_OBE_DrawElements */
ctx->ListState.ListVtxfmt.MultiDrawElementsEXT = _mesa_noop_MultiDrawElements;
+ ctx->ListState.ListVtxfmt.MultiDrawElementsBaseVertex = _mesa_noop_MultiDrawElementsBaseVertex;
_mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
}
diff --git a/src/mesa/vbo/vbo_split.c b/src/mesa/vbo/vbo_split.c
index 58e879628d..c445acca7d 100644
--- a/src/mesa/vbo/vbo_split.c
+++ b/src/mesa/vbo/vbo_split.c
@@ -50,6 +50,7 @@
#include "main/glheader.h"
#include "main/imports.h"
#include "main/mtypes.h"
+#include "main/macros.h"
#include "vbo_split.h"
#include "vbo.h"
@@ -107,7 +108,12 @@ void vbo_split_prims( GLcontext *ctx,
vbo_draw_func draw,
const struct split_limits *limits )
{
-
+ GLuint max_basevertex = prim->basevertex;
+ GLuint i;
+
+ for (i = 1; i < nr_prims; i++)
+ max_basevertex = MAX2(max_basevertex, prim[i].basevertex);
+
if (ib) {
if (limits->max_indices == 0) {
/* Could traverse the indices, re-emitting vertices in turn.
diff --git a/src/mesa/vbo/vbo_split_copy.c b/src/mesa/vbo/vbo_split_copy.c
index 8ec180d550..c45190b9dd 100644
--- a/src/mesa/vbo/vbo_split_copy.c
+++ b/src/mesa/vbo/vbo_split_copy.c
@@ -589,28 +589,40 @@ void vbo_split_copy( GLcontext *ctx,
const struct split_limits *limits )
{
struct copy_context copy;
- GLuint i;
+ GLuint i, this_nr_prims;
+
+ for (i = 0; i < nr_prims;) {
+ /* Our SW TNL pipeline doesn't handle basevertex yet, so bind_indices
+ * will rebase the elements to the basevertex, and we'll only
+ * emit strings of prims with the same basevertex in one draw call.
+ */
+ for (this_nr_prims = 1; i + this_nr_prims < nr_prims;
+ this_nr_prims++) {
+ if (prim[i].basevertex != prim[i + this_nr_prims].basevertex)
+ break;
+ }
- memset(&copy, 0, sizeof(copy));
+ memset(&copy, 0, sizeof(copy));
- /* Require indexed primitives:
- */
- assert(ib);
-
- copy.ctx = ctx;
- copy.array = arrays;
- copy.prim = prim;
- copy.nr_prims = nr_prims;
- copy.ib = ib;
- copy.draw = draw;
- copy.limits = limits;
+ /* Require indexed primitives:
+ */
+ assert(ib);
- /* Clear the vertex cache:
- */
- for (i = 0; i < ELT_TABLE_SIZE; i++)
- copy.vert_cache[i].in = ~0;
+ copy.ctx = ctx;
+ copy.array = arrays;
+ copy.prim = &prim[i];
+ copy.nr_prims = this_nr_prims;
+ copy.ib = ib;
+ copy.draw = draw;
+ copy.limits = limits;
- replay_init(&copy);
- replay_elts(&copy);
- replay_finish(&copy);
+ /* Clear the vertex cache:
+ */
+ for (i = 0; i < ELT_TABLE_SIZE; i++)
+ copy.vert_cache[i].in = ~0;
+
+ replay_init(&copy);
+ replay_elts(&copy);
+ replay_finish(&copy);
+ }
}