mesa: Branch 'vbo-0.2' - 2 commits
Keith Whitwell
keithw at kemper.freedesktop.org
Wed Jan 31 14:03:23 UTC 2007
src/mesa/drivers/dri/i965/brw_draw.c | 53 ++++++
src/mesa/drivers/dri/i965/brw_draw_upload.c | 105 ++-----------
src/mesa/sources | 1
src/mesa/tnl/t_draw.c | 108 ++++---------
src/mesa/vbo/vbo.h | 15 +
src/mesa/vbo/vbo_exec_array.c | 146 +++++++++---------
src/mesa/vbo/vbo_rebase.c | 222 ++++++++++++++++++++++++++++
src/mesa/vbo/vbo_split_copy.c | 1
src/mesa/vbo/vbo_split_inplace.c | 1
9 files changed, 420 insertions(+), 232 deletions(-)
New commits:
diff-tree 893526b8a823fe1b88f2b46376155afb91c84016 (from 240641de0c8532009fd21be7d4b0b84e471e91e8)
Author: Keith Whitwell <keith at tungstengraphics.com>
Date: Tue Jan 30 20:22:55 2007 +0000
Use new rebase helper. Remove other rebase code.
diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c
index 63cb079..7d8f837 100644
--- a/src/mesa/drivers/dri/i965/brw_draw.c
+++ b/src/mesa/drivers/dri/i965/brw_draw.c
@@ -198,7 +198,9 @@ static void brw_merge_inputs( struct brw
brw->state.dirty.brw |= BRW_NEW_INPUT_VARYING;
}
-
+/* XXX: could split the primitive list to fallback only on the
+ * non-conformant primitives.
+ */
static GLboolean check_fallbacks( struct brw_context *brw,
const struct _mesa_prim *prim,
GLuint nr_prims )
@@ -251,7 +253,9 @@ static GLboolean check_fallbacks( struct
return GL_FALSE;
}
-
+/* May fail if out of video memory for texture or vbo upload, or on
+ * fallback conditions.
+ */
static GLboolean brw_try_draw_prims( GLcontext *ctx,
const struct gl_client_array *arrays[],
const struct _mesa_prim *prim,
@@ -376,6 +380,33 @@ static GLboolean brw_try_draw_prims( GLc
return retval;
}
+static GLboolean brw_need_rebase( GLcontext *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index )
+{
+ if (min_index == 0)
+ return GL_FALSE;
+
+ if (ib) {
+ if (!vbo_all_varyings_in_vbos(arrays))
+ return GL_TRUE;
+ else
+ return GL_FALSE;
+ }
+ else {
+ /* Hmm. This isn't quite what I wanted. BRW can actually
+ * handle the mixed case well enough that we shouldn't need to
+ * rebase. However, it's probably not very common, nor hugely
+ * expensive to do it this way:
+ */
+ if (!vbo_all_varyings_in_vbos(arrays))
+ return GL_TRUE;
+ else
+ return GL_FALSE;
+ }
+}
+
void brw_draw_prims( GLcontext *ctx,
const struct gl_client_array *arrays[],
@@ -388,6 +419,21 @@ void brw_draw_prims( GLcontext *ctx,
struct intel_context *intel = intel_context(ctx);
GLboolean retval;
+ /* Decide if we want to rebase. If so we end up recursing once
+ * only into this function.
+ */
+ if (brw_need_rebase( ctx, arrays, ib, min_index )) {
+ vbo_rebase_prims( ctx, arrays,
+ prim, nr_prims,
+ ib, min_index, max_index,
+ brw_draw_prims );
+
+ return;
+ }
+
+
+ /* Make a first attempt at drawing:
+ */
retval = brw_try_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index);
@@ -440,14 +486,13 @@ void brw_draw_init( struct brw_context *
for (i = 0; i < BRW_NR_UPLOAD_BUFS; i++) {
brw->vb.upload.vbo[i] = ctx->Driver.NewBufferObject(ctx, 1, GL_ARRAY_BUFFER_ARB);
- /* XXX: Set these to no-backing-store
+ /* NOTE: These are set to no-backing-store.
*/
bmBufferSetInvalidateCB(&brw->intel,
intel_bufferobj_buffer(intel_buffer_object(brw->vb.upload.vbo[i])),
brw_invalidate_vbo_cb,
&brw->intel,
GL_TRUE);
-
}
ctx->Driver.BufferData( ctx,
diff --git a/src/mesa/drivers/dri/i965/brw_draw_upload.c b/src/mesa/drivers/dri/i965/brw_draw_upload.c
index 90637d1..6968d74 100644
--- a/src/mesa/drivers/dri/i965/brw_draw_upload.c
+++ b/src/mesa/drivers/dri/i965/brw_draw_upload.c
@@ -309,7 +309,6 @@ copy_array_to_vbo_array( struct brw_cont
GLuint i,
const struct gl_client_array *array,
GLuint element_size,
- GLuint min_index,
GLuint count)
{
GLcontext *ctx = &brw->intel.ctx;
@@ -347,7 +346,7 @@ copy_array_to_vbo_array( struct brw_cont
map += offset;
copy_strided_array( map,
- array->Ptr + min_index * array->StrideB,
+ array->Ptr,
element_size,
array->StrideB,
count);
@@ -438,10 +437,8 @@ GLboolean brw_upload_vertices( struct br
}
upload[nr_uploads++] = input;
- input->vbo_rebase_offset = 0;
+ assert(min_index == 0);
}
- else
- input->vbo_rebase_offset = min_index * input->glarray->StrideB;
}
/* Upload interleaved arrays if all uploads are interleaved
@@ -454,7 +451,6 @@ GLboolean brw_upload_vertices( struct br
input0->glarray = copy_array_to_vbo_array(brw, 0,
input0->glarray,
interleave,
- min_index,
input0->count);
for (i = 1; i < nr_uploads; i++) {
@@ -472,7 +468,6 @@ GLboolean brw_upload_vertices( struct br
input->glarray = copy_array_to_vbo_array(brw, i,
input->glarray,
input->element_size,
- min_index,
input->count);
}
@@ -520,9 +515,9 @@ GLboolean brw_upload_vertices( struct br
vbp.vb[i].vb0.bits.pad = 0;
vbp.vb[i].vb0.bits.access_type = BRW_VERTEXBUFFER_ACCESS_VERTEXDATA;
vbp.vb[i].vb0.bits.vb_index = i;
- vbp.vb[i].offset = (GLuint)input->glarray->Ptr + input->vbo_rebase_offset;
+ vbp.vb[i].offset = (GLuint)input->glarray->Ptr;
vbp.vb[i].buffer = array_buffer(input->glarray);
- vbp.vb[i].max_index = max_index - min_index;
+ vbp.vb[i].max_index = max_index;
}
@@ -563,94 +558,32 @@ static GLuint element_size( GLenum type
-
-static void rebase_indices_to_vbo_indices( struct brw_context *brw,
- const struct _mesa_index_buffer *index_buffer,
- struct gl_buffer_object **vbo_return,
- GLuint *offset_return )
+void brw_upload_indices( struct brw_context *brw,
+ const struct _mesa_index_buffer *index_buffer )
{
GLcontext *ctx = &brw->intel.ctx;
- GLuint min_index = index_buffer->rebase;
- const void *indices = index_buffer->ptr;
- GLsizei count = index_buffer->count;
- GLenum type = index_buffer->type;
- GLuint size = element_size(type) * count;
- struct gl_buffer_object *bufferobj;
- GLuint offset;
- GLuint i;
-
- get_space(brw, size, &bufferobj, &offset);
+ struct intel_context *intel = &brw->intel;
+ GLuint ib_size = get_size(index_buffer->type) * index_buffer->count;
+ struct gl_buffer_object *bufferobj = index_buffer->obj;
+ GLuint offset = (GLuint)index_buffer->ptr;
- *vbo_return = bufferobj;
- *offset_return = offset;
+ /* Turn into a proper VBO:
+ */
+ if (!bufferobj->Name) {
+
+ /* Get new bufferobj, offset:
+ */
+ get_space(brw, ib_size, &bufferobj, &offset);
- if (min_index == 0) {
/* Straight upload
*/
ctx->Driver.BufferSubData( ctx,
GL_ELEMENT_ARRAY_BUFFER_ARB,
offset,
- size,
- indices,
+ ib_size,
+ index_buffer->ptr,
bufferobj);
}
- else {
- void *map = ctx->Driver.MapBuffer(ctx,
- GL_ELEMENT_ARRAY_BUFFER_ARB,
- GL_DYNAMIC_DRAW_ARB,
- bufferobj);
-
- map += offset;
-
- switch (type) {
- case GL_UNSIGNED_INT: {
- GLuint *ui_map = (GLuint *)map;
- const GLuint *ui_indices = (const GLuint *)indices;
-
- for (i = 0; i < count; i++)
- ui_map[i] = ui_indices[i] - min_index;
- break;
- }
- case GL_UNSIGNED_SHORT: {
- GLushort *us_map = (GLushort *)map;
- const GLushort *us_indices = (const GLushort *)indices;
-
- for (i = 0; i < count; i++)
- us_map[i] = us_indices[i] - min_index;
- break;
- }
- case GL_UNSIGNED_BYTE: {
- GLubyte *ub_map = (GLubyte *)map;
- const GLubyte *ub_indices = (const GLubyte *)indices;
-
- for (i = 0; i < count; i++)
- ub_map[i] = ub_indices[i] - min_index;
- break;
- }
- }
-
- ctx->Driver.UnmapBuffer(ctx,
- GL_ELEMENT_ARRAY_BUFFER_ARB,
- bufferobj);
-
- }
-}
-
-
-
-void brw_upload_indices( struct brw_context *brw,
- const struct _mesa_index_buffer *index_buffer)
-{
- struct intel_context *intel = &brw->intel;
- GLuint ib_size = get_size(index_buffer->type) * index_buffer->count;
- struct gl_buffer_object *bufferobj = index_buffer->obj;
- GLuint offset = (GLuint)index_buffer->ptr;
-
- /* Already turned into a proper VBO:
- */
- if (!index_buffer->obj->Name) {
- rebase_indices_to_vbo_indices(brw, index_buffer, &bufferobj, &offset );
- }
/* Emit the indexbuffer packet:
*/
diff --git a/src/mesa/tnl/t_draw.c b/src/mesa/tnl/t_draw.c
index 0e7c2b6..c97cf5f 100644
--- a/src/mesa/tnl/t_draw.c
+++ b/src/mesa/tnl/t_draw.c
@@ -95,18 +95,14 @@ static void free_space(GLcontext *ctx)
*/
static void _tnl_import_array( GLcontext *ctx,
GLuint attrib,
- GLuint start,
- GLuint end,
+ GLuint count,
const struct gl_client_array *input,
const GLubyte *ptr )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
- const GLuint count = end - start;
GLuint stride = input->StrideB;
- ptr += start * stride;
-
if (input->Type != GL_FLOAT) {
const GLuint sz = input->Size;
GLubyte *buf = get_space(ctx, count * sz * sizeof(GLfloat));
@@ -183,7 +179,7 @@ static GLboolean *_tnl_import_edgeflag(
static void bind_inputs( GLcontext *ctx,
const struct gl_client_array *inputs[],
- GLint min_index, GLint max_index,
+ GLint count,
struct gl_buffer_object **bo,
GLuint *nr_bo )
{
@@ -215,18 +211,17 @@ static void bind_inputs( GLcontext *ctx,
ptr = inputs[i]->Ptr;
/* Just make sure the array is floating point, otherwise convert to
- * temporary storage. Rebase arrays so that 'min_index' becomes
- * element zero.
+ * temporary storage.
*
* XXX: remove the GLvector4f type at some stage and just use
* client arrays.
*/
- _tnl_import_array(ctx, i, min_index, max_index, inputs[i], ptr);
+ _tnl_import_array(ctx, i, count, inputs[i], ptr);
}
/* We process only the vertices between min & max index:
*/
- VB->Count = max_index - min_index;
+ VB->Count = count;
/* Legacy pointers -- remove one day.
@@ -264,7 +259,6 @@ static void bind_inputs( GLcontext *ctx,
*/
static void bind_indices( GLcontext *ctx,
const struct _mesa_index_buffer *ib,
- GLuint min_index,
struct gl_buffer_object **bo,
GLuint *nr_bo)
{
@@ -273,8 +267,10 @@ static void bind_indices( GLcontext *ctx
GLuint i;
void *ptr;
- if (!ib)
+ if (!ib) {
+ VB->Elts = NULL;
return;
+ }
if (ib->obj->Name && !ib->obj->Pointer) {
bo[*nr_bo] = ib->obj;
@@ -289,60 +285,34 @@ static void bind_indices( GLcontext *ctx
ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr);
- if (ib->type == GL_UNSIGNED_INT && min_index == 0) {
+ if (ib->type == GL_UNSIGNED_INT) {
VB->Elts = (GLuint *) ptr;
- VB->Elts += ib->rebase;
}
else {
GLuint *elts = (GLuint *)get_space(ctx, ib->count * sizeof(GLuint));
VB->Elts = elts;
- switch (ib->type) {
- case GL_UNSIGNED_INT: {
- const GLuint *in = ((GLuint *)ptr) + ib->rebase;
- for (i = 0; i < ib->count; i++)
- *elts++ = *in++ - min_index;
- break;
- }
- case GL_UNSIGNED_SHORT: {
- const GLushort *in = ((GLushort *)ptr) + ib->rebase;
+ if (ib->type == GL_UNSIGNED_SHORT) {
+ const GLushort *in = (GLushort *)ptr;
for (i = 0; i < ib->count; i++)
- *elts++ = (GLuint)(*in++) - min_index;
- break;
+ *elts++ = (GLuint)(*in++);
}
- case GL_UNSIGNED_BYTE: {
- const GLubyte *in = ((GLubyte *)ptr) + ib->rebase;
+ else {
+ const GLubyte *in = (GLubyte *)ptr;
for (i = 0; i < ib->count; i++)
- *elts++ = (GLuint)(*in++) - min_index;
- break;
+ *elts++ = (GLuint)(*in++);
}
- }
}
}
static void bind_prims( GLcontext *ctx,
const struct _mesa_prim *prim,
- GLuint nr_prims,
- GLuint min_index )
+ GLuint nr_prims )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
- GLuint i;
-
- if (min_index != 0) {
- struct _mesa_prim *tmp = (struct _mesa_prim *)get_space(ctx, nr_prims * sizeof(*prim));
-
- for (i = 0; i < nr_prims; i++) {
- tmp[i] = prim[i];
- tmp[i].start -= min_index;
- }
-
- VB->Primitive = tmp;
- }
- else {
- VB->Primitive = prim;
- }
+ VB->Primitive = prim;
VB->PrimitiveCount = nr_prims;
}
@@ -373,19 +343,10 @@ void _tnl_draw_prims( GLcontext *ctx,
GLuint max_index)
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct vertex_buffer *VB = &tnl->vb;
- GLint max = VB->Size;
-
-#ifdef TEST_SPLIT
- max = 8 + MAX_CLIPPED_VERTICES;
-#endif
-
- assert(max_index > min_index);
- assert(!(max_index & 0x80000000));
+ const GLuint TEST_SPLIT = 0;
+ const GLint max = TEST_SPLIT ? 8 : tnl->vb.Size - MAX_CLIPPED_VERTICES;
- VB->Elts = NULL;
-
-#if 0
+ if (0)
{
GLuint i;
_mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
@@ -395,15 +356,22 @@ void _tnl_draw_prims( GLcontext *ctx,
prim[i].start,
prim[i].count);
}
-#endif
- /* The software TNL pipeline has a fixed amount of storage for
- * vertices and it is necessary to split incoming drawing commands
- * if they exceed that limit.
- */
- if (max_index - min_index >= max - MAX_CLIPPED_VERTICES) {
+ if (min_index) {
+ /* We always translate away calls with min_index != 0.
+ */
+ vbo_rebase_prims( ctx, arrays, prim, nr_prims, ib,
+ min_index, max_index,
+ _tnl_draw_prims );
+ return;
+ }
+ else if (max_index >= max) {
+ /* The software TNL pipeline has a fixed amount of storage for
+ * vertices and it is necessary to split incoming drawing commands
+ * if they exceed that limit.
+ */
struct split_limits limits;
- limits.max_verts = max - MAX_CLIPPED_VERTICES;
+ limits.max_verts = max;
limits.max_vb_size = ~0;
limits.max_indices = ~0;
@@ -411,7 +379,7 @@ void _tnl_draw_prims( GLcontext *ctx,
* recursively call back into this function.
*/
vbo_split_prims( ctx, arrays, prim, nr_prims, ib,
- min_index, max_index,
+ 0, max_index,
_tnl_draw_prims,
&limits );
}
@@ -425,9 +393,9 @@ void _tnl_draw_prims( GLcontext *ctx,
/* Binding inputs may imply mapping some vertex buffer objects.
* They will need to be unmapped below.
*/
- bind_inputs(ctx, arrays, min_index, max_index+1, bo, &nr_bo);
- bind_indices(ctx, ib, min_index, bo, &nr_bo);
- bind_prims(ctx, prim, nr_prims, VB->Elts ? 0 : min_index );
+ bind_inputs(ctx, arrays, max_index+1, bo, &nr_bo);
+ bind_indices(ctx, ib, bo, &nr_bo);
+ bind_prims(ctx, prim, nr_prims );
TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx);
diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h
index 6a6fb28..874a5f9 100644
--- a/src/mesa/vbo/vbo.h
+++ b/src/mesa/vbo/vbo.h
@@ -55,7 +55,6 @@ struct _mesa_index_buffer {
GLenum type;
struct gl_buffer_object *obj;
const void *ptr;
- GLuint rebase;
};
diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c
index 5a3a748..f96df5f 100644
--- a/src/mesa/vbo/vbo_exec_array.c
+++ b/src/mesa/vbo/vbo_exec_array.c
@@ -34,45 +34,55 @@
#include "vbo_context.h"
-static GLuint get_max_index( GLuint count, GLuint type,
- const GLvoid *indices )
+/* Compute min and max elements for drawelements calls.
+ */
+static void get_minmax_index( GLuint count, GLuint type,
+ const GLvoid *indices,
+ GLuint *min_index,
+ GLuint *max_index)
{
GLint i;
- /* Compute max element. This is only needed for upload of non-VBO,
- * non-constant data elements.
- *
- * XXX: Postpone this calculation until it is known that it is
- * needed. Otherwise could scan this pointlessly in the all-vbo
- * case.
- */
switch(type) {
case GL_UNSIGNED_INT: {
const GLuint *ui_indices = (const GLuint *)indices;
- GLuint max_ui = 0;
- for (i = 0; i < count; i++)
- if (ui_indices[i] > max_ui)
- max_ui = ui_indices[i];
- return max_ui;
+ GLuint max_ui = ui_indices[0];
+ GLuint min_ui = ui_indices[0];
+ for (i = 1; i < count; i++) {
+ if (ui_indices[i] > max_ui) max_ui = ui_indices[i];
+ if (ui_indices[i] < min_ui) min_ui = ui_indices[i];
+ }
+ *min_index = min_ui;
+ *max_index = max_ui;
+ break;
}
case GL_UNSIGNED_SHORT: {
const GLushort *us_indices = (const GLushort *)indices;
- GLuint max_us = 0;
- for (i = 0; i < count; i++)
- if (us_indices[i] > max_us)
- max_us = us_indices[i];
- return max_us;
+ GLuint max_us = us_indices[0];
+ GLuint min_us = us_indices[0];
+ for (i = 1; i < count; i++) {
+ if (us_indices[i] > max_us) max_us = us_indices[i];
+ if (us_indices[i] < min_us) min_us = us_indices[i];
+ }
+ *min_index = min_us;
+ *max_index = max_us;
+ break;
}
case GL_UNSIGNED_BYTE: {
const GLubyte *ub_indices = (const GLubyte *)indices;
- GLuint max_ub = 0;
- for (i = 0; i < count; i++)
- if (ub_indices[i] > max_ub)
- max_ub = ub_indices[i];
- return max_ub;
+ GLuint max_ub = ub_indices[0];
+ GLuint min_ub = ub_indices[0];
+ for (i = 1; i < count; i++) {
+ if (ub_indices[i] > max_ub) max_ub = ub_indices[i];
+ if (ub_indices[i] < min_ub) min_ub = ub_indices[i];
+ }
+ *min_index = min_ub;
+ *max_index = max_ub;
+ break;
}
default:
- return 0;
+ assert(0);
+ break;
}
}
@@ -241,31 +251,12 @@ vbo_exec_DrawArrays(GLenum mode, GLint s
prim[0].end = 1;
prim[0].weak = 0;
prim[0].pad = 0;
+ prim[0].mode = mode;
+ prim[0].start = start;
+ prim[0].count = count;
+ prim[0].indexed = 0;
- if (exec->array.inputs[0]->BufferObj->Name) {
- /* Use vertex attribute as a hint to tell us if we expect all
- * arrays to be in VBO's and if so, don't worry about avoiding
- * the upload of elements < start.
- */
- prim[0].mode = mode;
- prim[0].start = start;
- prim[0].count = count;
- prim[0].indexed = 0;
-
- vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, 0, start + count );
- }
- else {
- /* If not using VBO's, we don't want to upload any more elements
- * than necessary from the arrays as they will not be valid next
- * time the application tries to draw with them.
- */
- prim[0].mode = mode;
- prim[0].start = 0;
- prim[0].count = count;
- prim[0].indexed = 0;
-
- vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, start, start + count );
- }
+ vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, start, start + count - 1 );
}
@@ -296,20 +287,6 @@ vbo_exec_DrawRangeElements(GLenum mode,
ib.obj = ctx->Array.ElementArrayBufferObj;
ib.ptr = indices;
- if (ctx->Array.ElementArrayBufferObj->Name) {
- /* Use the fact that indices are in a VBO as a hint that the
- * program has put all the arrays in VBO's and we don't have to
- * worry about performance implications of start > 0.
- *
- * XXX: consider passing start as min_index to draw_prims instead.
- * XXX: don't rebase because it didn't work.
- */
- ib.rebase = 0;
- }
- else {
- ib.rebase = /*start*/ 0;
- }
-
prim[0].begin = 1;
prim[0].end = 1;
prim[0].weak = 0;
@@ -319,15 +296,46 @@ vbo_exec_DrawRangeElements(GLenum mode,
prim[0].count = count;
prim[0].indexed = 1;
- vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib, /*ib.rebase*/ start, end+1 );
-}
+ /* Need to give special consideration to rendering a range of
+ * indices starting somewhere above zero. Typically the
+ * application is issuing multiple DrawRangeElements() to draw
+ * successive primitives layed out linearly in the vertex arrays.
+ * Unless the vertex arrays are all in a VBO (or locked as with
+ * CVA), the OpenGL semantics imply that we need to re-read or
+ * re-upload the vertex data on each draw call.
+ *
+ * In the case of hardware tnl, we want to avoid starting the
+ * upload at zero, as it will mean every draw call uploads an
+ * increasing amount of not-used vertex data. Worse - in the
+ * software tnl module, all those vertices might be transformed and
+ * lit but never rendered.
+ *
+ * If we just upload or transform the vertices in start..end,
+ * however, the indices will be incorrect.
+ *
+ * At this level, we don't know exactly what the requirements of
+ * the backend are going to be, though it will likely boil down to
+ * either:
+ *
+ * 1) Do nothing, everything is in a VBO and is processed once
+ * only.
+ *
+ * 2) Adjust the indices and vertex arrays so that start becomes
+ * zero.
+ *
+ * Rather than doing anything here, I'll provide a helper function
+ * for the latter case elsewhere.
+ */
+ vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib, start, end );
+}
static void GLAPIENTRY
vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
{
GET_CURRENT_CONTEXT(ctx);
- GLuint max_index;
+ GLuint min_index = 0;
+ GLuint max_index = 0;
if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices ))
return;
@@ -338,17 +346,17 @@ vbo_exec_DrawElements(GLenum mode, GLsiz
GL_READ_ONLY,
ctx->Array.ElementArrayBufferObj);
- max_index = get_max_index(count, type, ADD_POINTERS(map, indices));
+ get_minmax_index(count, type, ADD_POINTERS(map, indices), &min_index, &max_index);
ctx->Driver.UnmapBuffer(ctx,
GL_ELEMENT_ARRAY_BUFFER_ARB,
ctx->Array.ElementArrayBufferObj);
}
else {
- max_index = get_max_index(count, type, indices);
+ get_minmax_index(count, type, indices, &min_index, &max_index);
}
- vbo_exec_DrawRangeElements(mode, 0, max_index, count, type, indices);
+ vbo_exec_DrawRangeElements(mode, min_index, max_index, count, type, indices);
}
diff --git a/src/mesa/vbo/vbo_rebase.c b/src/mesa/vbo/vbo_rebase.c
index 2a6f037..bc4211d 100644
--- a/src/mesa/vbo/vbo_rebase.c
+++ b/src/mesa/vbo/vbo_rebase.c
@@ -123,7 +123,8 @@ void vbo_rebase_prims( GLcontext *ctx,
assert(min_index != 0);
- _mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
+ if (0)
+ _mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
if (ib) {
/* Unfortunately need to adjust each index individually.
diff --git a/src/mesa/vbo/vbo_split_copy.c b/src/mesa/vbo/vbo_split_copy.c
index d9c5853..ef97acb 100644
--- a/src/mesa/vbo/vbo_split_copy.c
+++ b/src/mesa/vbo/vbo_split_copy.c
@@ -479,7 +479,6 @@ static void replay_init( struct copy_con
copy->dstib.type = GL_UNSIGNED_INT;
copy->dstib.obj = ctx->Array.NullBufferObj;
copy->dstib.ptr = copy->dstelt;
- copy->dstib.rebase = 0;
}
diff --git a/src/mesa/vbo/vbo_split_inplace.c b/src/mesa/vbo/vbo_split_inplace.c
index d3649c5..ea62866 100644
--- a/src/mesa/vbo/vbo_split_inplace.c
+++ b/src/mesa/vbo/vbo_split_inplace.c
@@ -223,7 +223,6 @@ static void split_prims( struct split_co
ib.type = GL_UNSIGNED_INT;
ib.obj = split->ctx->Array.NullBufferObj;
ib.ptr = elts;
- ib.rebase = 0; /* ? */
tmpprim = *prim;
tmpprim.indexed = 1;
diff-tree 240641de0c8532009fd21be7d4b0b84e471e91e8 (from 48c638b6712734a09b6d8632045b0e905195e345)
Author: Keith Whitwell <keith at tungstengraphics.com>
Date: Tue Jan 30 19:27:53 2007 +0000
Helper for rebasing draw requests where min_index != 0.
diff --git a/src/mesa/sources b/src/mesa/sources
index fd6e8b4..6d6d228 100644
--- a/src/mesa/sources
+++ b/src/mesa/sources
@@ -143,6 +143,7 @@ VBO_SOURCES = \
vbo/vbo_exec_array.c \
vbo/vbo_exec_draw.c \
vbo/vbo_exec_eval.c \
+ vbo/vbo_rebase.c \
vbo/vbo_split.c \
vbo/vbo_split_copy.c \
vbo/vbo_split_inplace.c \
diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h
index c81d83f..6a6fb28 100644
--- a/src/mesa/vbo/vbo.h
+++ b/src/mesa/vbo/vbo.h
@@ -101,4 +101,18 @@ void vbo_split_prims( GLcontext *ctx,
const struct split_limits *limits );
+/* Helpers for dealing translating away non-zero min_index.
+ */
+GLboolean vbo_all_varyings_in_vbos( const struct gl_client_array *arrays[] );
+
+void vbo_rebase_prims( GLcontext *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index,
+ vbo_draw_func draw );
+
+
#endif
diff --git a/src/mesa/vbo/vbo_rebase.c b/src/mesa/vbo/vbo_rebase.c
new file mode 100644
index 0000000..2a6f037
--- /dev/null
+++ b/src/mesa/vbo/vbo_rebase.c
@@ -0,0 +1,221 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith at tungstengraphics.com>
+ */
+
+/* Helper for drivers which find themselves rendering a range of
+ * indices starting somewhere above zero. Typically the application
+ * is issuing multiple DrawArrays() or DrawElements() to draw
+ * successive primitives layed out linearly in the vertex arrays.
+ * Unless the vertex arrays are all in a VBO, the OpenGL semantics
+ * imply that we need to re-upload the vertex data on each draw call.
+ * In that case, we want to avoid starting the upload at zero, as it
+ * will mean every draw call uploads an increasing amount of not-used
+ * vertex data. Worse - in the software tnl module, all those
+ * vertices will be transformed and lit.
+ *
+ * If we just upload the new data, however, the indices will be
+ * incorrect as we tend to upload each set of vertex data to a new
+ * region.
+ *
+ * This file provides a helper to adjust the arrays, primitives and
+ * indices of a draw call so that it can be re-issued with a min_index
+ * of zero.
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "mtypes.h"
+
+#include "vbo.h"
+
+
+#define REBASE(TYPE) \
+static void *rebase_##TYPE( const void *ptr, \
+ GLuint count, \
+ TYPE min_index ) \
+{ \
+ const TYPE *in = (TYPE *)ptr; \
+ TYPE *tmp_indices = malloc(count * sizeof(TYPE)); \
+ GLuint i; \
+ \
+ for (i = 0; i < count; i++) \
+ tmp_indices[i] = in[i] - min_index; \
+ \
+ return (void *)tmp_indices; \
+}
+
+
+REBASE(GLuint)
+REBASE(GLushort)
+REBASE(GLubyte)
+
+GLboolean vbo_all_varyings_in_vbos( const struct gl_client_array *arrays[] )
+{
+ GLuint i;
+
+ for (i = 0; i < VERT_ATTRIB_MAX; i++)
+ if (arrays[i]->StrideB &&
+ arrays[i]->BufferObj->Name == 0)
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+/* Adjust primitives, indices and vertex definitions so that min_index
+ * becomes zero. There are lots of reasons for wanting to do this, eg:
+ *
+ * Software tnl:
+ * - any time min_index != 0, otherwise unused vertices lower than
+ * min_index will be transformed.
+ *
+ * Hardware tnl:
+ * - if ib != NULL and min_index != 0, otherwise vertices lower than
+ * min_index will be uploaded. Requires adjusting index values.
+ *
+ * - if ib == NULL and min_index != 0, just for convenience so this doesn't
+ * have to be handled within the driver.
+ *
+ * Hardware tnl with VBO support:
+ * - as above, but only when vertices are not (all?) in VBO's.
+ * - can't save time by trying to upload half a vbo - typically it is
+ * all or nothing.
+ */
+void vbo_rebase_prims( GLcontext *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index,
+ vbo_draw_func draw )
+{
+ struct gl_client_array tmp_arrays[VERT_ATTRIB_MAX];
+ const struct gl_client_array *tmp_array_pointers[VERT_ATTRIB_MAX];
+
+ struct _mesa_index_buffer tmp_ib;
+ struct _mesa_prim *tmp_prims = NULL;
+ void *tmp_indices = NULL;
+ GLuint i;
+
+ assert(min_index != 0);
+
+ _mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
+
+ if (ib) {
+ /* Unfortunately need to adjust each index individually.
+ */
+ GLboolean map_ib = ib->obj->Name && !ib->obj->Pointer;
+ void *ptr;
+
+ if (map_ib)
+ ctx->Driver.MapBuffer(ctx,
+ GL_ELEMENT_ARRAY_BUFFER,
+ GL_READ_ONLY_ARB,
+ ib->obj);
+
+
+ ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr);
+
+ /* Some users might prefer it if we translated elements to
+ * GLuints here. Others wouldn't...
+ */
+ switch (ib->type) {
+ case GL_UNSIGNED_INT:
+ tmp_indices = rebase_GLuint( ptr, ib->count, min_index );
+ break;
+ case GL_UNSIGNED_SHORT:
+ tmp_indices = rebase_GLushort( ptr, ib->count, min_index );
+ break;
+ case GL_UNSIGNED_BYTE:
+ tmp_indices = rebase_GLubyte( ptr, ib->count, min_index );
+ break;
+ }
+
+ if (map_ib)
+ ctx->Driver.UnmapBuffer(ctx,
+ GL_ELEMENT_ARRAY_BUFFER,
+ ib->obj);
+
+ tmp_ib.obj = ctx->Array.NullBufferObj;
+ tmp_ib.ptr = tmp_indices;
+ tmp_ib.count = ib->count;
+ tmp_ib.type = ib->type;
+
+ ib = &tmp_ib;
+ }
+ else {
+ /* Otherwise the primitives need adjustment.
+ */
+ tmp_prims = (struct _mesa_prim *)_mesa_malloc(sizeof(*prim) * nr_prims);
+
+ for (i = 0; i < nr_prims; i++) {
+ /* If this fails, it could indicate an application error:
+ */
+ assert(prim[i].start >= min_index);
+
+ tmp_prims[i] = prim[i];
+ tmp_prims[i].start -= min_index;
+ }
+
+ prim = tmp_prims;
+ }
+
+ /* Just need to adjust the pointer values on each incoming array.
+ * This works for VBO and non-vbo rendering and shouldn't pesimize
+ * VBO-based upload schemes. However this may still not be a fast
+ * path for hardware tnl for VBO based rendering as most machines
+ * will be happier if you just specify a starting vertex value in
+ * each primitive.
+ *
+ * For drivers with hardware tnl, you only want to do this if you
+ * are forced to, eg non-VBO indexed rendering with start != 0.
+ */
+ for (i = 0; i < VERT_ATTRIB_MAX; i++) {
+ tmp_arrays[i] = *arrays[i];
+ tmp_arrays[i].Ptr += min_index * tmp_arrays[i].StrideB;
+ tmp_array_pointers[i] = &tmp_arrays[i];
+ }
+
+ /* Re-issue the draw call.
+ */
+ draw( ctx,
+ tmp_array_pointers,
+ prim,
+ nr_prims,
+ ib,
+ 0,
+ max_index - min_index );
+
+ if (tmp_indices)
+ _mesa_free(tmp_indices);
+
+ if (tmp_prims)
+ _mesa_free(tmp_prims);
+}
+
+
+
More information about the mesa-commit
mailing list