From b9d0f947f2bcc47047b162e3d7c8f91b6153e02c Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Wed, 6 May 2009 15:17:25 -0600 Subject: [PATCH] mesa: Compute gl_client_array->_MaxElement during array validation Used to be done in the glVertex/Normal/Color/etc/Pointer() calls but if the VBO was reallocated the size could change. New _NEW_BUFFER_OBJECT state flag. --- src/mesa/main/bufferobj.c | 2 + src/mesa/main/mtypes.h | 1 + src/mesa/main/state.c | 88 +++++++++++++++++++++++++++------------ src/mesa/main/varray.c | 13 ------ 4 files changed, 64 insertions(+), 40 deletions(-) diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c index c8d160baa9a..49f690ddd2e 100644 --- a/src/mesa/main/bufferobj.c +++ b/src/mesa/main/bufferobj.c @@ -958,6 +958,8 @@ _mesa_BufferDataARB(GLenum target, GLsizeiptrARB size, bufObj->Pointer = NULL; } + FLUSH_VERTICES(ctx, _NEW_BUFFER_OBJECT); + ASSERT(ctx->Driver.BufferData); /* Give the buffer object to the driver! may be null! */ diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 716e5c655d8..368acde7a19 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -2619,6 +2619,7 @@ struct gl_matrix_stack #define _NEW_PROGRAM 0x8000000 /**< __GLcontextRec::VertexProgram */ #define _NEW_CURRENT_ATTRIB 0x10000000 /**< __GLcontextRec::Current */ #define _NEW_PROGRAM_CONSTANTS 0x20000000 +#define _NEW_BUFFER_OBJECT 0x40000000 #define _NEW_ALL ~0 /*@}*/ diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c index 47e1aaa7281..a6411f7b621 100644 --- a/src/mesa/main/state.c +++ b/src/mesa/main/state.c @@ -64,97 +64,131 @@ update_separate_specular(GLcontext *ctx) /** - * Update state dependent on vertex arrays. + * Compute the index of the last array element that can be safely accessed + * in a vertex array. We can really only do this when the array lives in + * a VBO. + * The array->_MaxElement field will be updated. + * Later in glDrawArrays/Elements/etc we can do some bounds checking. + */ +static void +compute_max_element(struct gl_client_array *array) +{ + assert(array->Enabled); + if (array->BufferObj->Name) { + /* Compute the max element we can access in the VBO without going + * out of bounds. + */ + array->_MaxElement = ((GLsizeiptrARB) array->BufferObj->Size + - (GLsizeiptrARB) array->Ptr + array->StrideB + - array->_ElementSize) / array->StrideB; + } + else { + /* user-space array, no idea how big it is */ + array->_MaxElement = 2 * 1000 * 1000 * 1000; /* just a big number */ + } +} + + +/** + * Helper for update_arrays(). + * \return min(current min, array->_MaxElement). + */ +static GLuint +update_min(GLuint min, struct gl_client_array *array) +{ + compute_max_element(array); + return MIN2(min, array->_MaxElement); +} + + +/** + * Update ctx->Array._MaxElement (the max legal index into all enabled arrays). + * Need to do this upon new array state or new buffer object state. */ static void update_arrays( GLcontext *ctx ) { - const struct gl_array_object *arrayObj = ctx->Array.ArrayObj; - GLuint i, min; + struct gl_array_object *arrayObj = ctx->Array.ArrayObj; + GLuint i, min = ~0; /* find min of _MaxElement values for all enabled arrays */ /* 0 */ if (ctx->VertexProgram._Current && arrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled) { - min = arrayObj->VertexAttrib[VERT_ATTRIB_POS]._MaxElement; + min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_POS]); } else if (arrayObj->Vertex.Enabled) { - min = arrayObj->Vertex._MaxElement; - } - else { - /* can't draw anything without vertex positions! */ - min = 0; + min = update_min(min, &arrayObj->Vertex); } /* 1 */ if (ctx->VertexProgram._Enabled && arrayObj->VertexAttrib[VERT_ATTRIB_WEIGHT].Enabled) { - min = MIN2(min, arrayObj->VertexAttrib[VERT_ATTRIB_WEIGHT]._MaxElement); + min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_WEIGHT]); } /* no conventional vertex weight array */ /* 2 */ if (ctx->VertexProgram._Enabled && arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL].Enabled) { - min = MIN2(min, arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL]._MaxElement); + min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL]); } else if (arrayObj->Normal.Enabled) { - min = MIN2(min, arrayObj->Normal._MaxElement); + min = update_min(min, &arrayObj->Normal); } /* 3 */ if (ctx->VertexProgram._Enabled && arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0].Enabled) { - min = MIN2(min, arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0]._MaxElement); + min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0]); } else if (arrayObj->Color.Enabled) { - min = MIN2(min, arrayObj->Color._MaxElement); + min = update_min(min, &arrayObj->Color); } /* 4 */ if (ctx->VertexProgram._Enabled && arrayObj->VertexAttrib[VERT_ATTRIB_COLOR1].Enabled) { - min = MIN2(min, arrayObj->VertexAttrib[VERT_ATTRIB_COLOR1]._MaxElement); + min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR1]); } else if (arrayObj->SecondaryColor.Enabled) { - min = MIN2(min, arrayObj->SecondaryColor._MaxElement); + min = update_min(min, &arrayObj->SecondaryColor); } /* 5 */ if (ctx->VertexProgram._Enabled && arrayObj->VertexAttrib[VERT_ATTRIB_FOG].Enabled) { - min = MIN2(min, arrayObj->VertexAttrib[VERT_ATTRIB_FOG]._MaxElement); + min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_FOG]); } else if (arrayObj->FogCoord.Enabled) { - min = MIN2(min, arrayObj->FogCoord._MaxElement); + min = update_min(min, &arrayObj->FogCoord); } /* 6 */ if (ctx->VertexProgram._Enabled && arrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled) { - min = MIN2(min, arrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX]._MaxElement); + min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX]); } else if (arrayObj->Index.Enabled) { - min = MIN2(min, arrayObj->Index._MaxElement); + min = update_min(min, &arrayObj->Index); } - /* 7 */ if (ctx->VertexProgram._Enabled && arrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled) { - min = MIN2(min, arrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG]._MaxElement); + min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG]); } /* 8..15 */ for (i = VERT_ATTRIB_TEX0; i <= VERT_ATTRIB_TEX7; i++) { if (ctx->VertexProgram._Enabled && arrayObj->VertexAttrib[i].Enabled) { - min = MIN2(min, arrayObj->VertexAttrib[i]._MaxElement); + min = update_min(min, &arrayObj->VertexAttrib[i]); } else if (i - VERT_ATTRIB_TEX0 < ctx->Const.MaxTextureCoordUnits && arrayObj->TexCoord[i - VERT_ATTRIB_TEX0].Enabled) { - min = MIN2(min, arrayObj->TexCoord[i - VERT_ATTRIB_TEX0]._MaxElement); + min = update_min(min, &arrayObj->TexCoord[i - VERT_ATTRIB_TEX0]); } } @@ -162,13 +196,13 @@ update_arrays( GLcontext *ctx ) if (ctx->VertexProgram._Current) { for (i = VERT_ATTRIB_GENERIC0; i < VERT_ATTRIB_MAX; i++) { if (arrayObj->VertexAttrib[i].Enabled) { - min = MIN2(min, arrayObj->VertexAttrib[i]._MaxElement); + min = update_min(min, &arrayObj->VertexAttrib[i]); } } } if (arrayObj->EdgeFlag.Enabled) { - min = MIN2(min, arrayObj->EdgeFlag._MaxElement); + min = update_min(min, &arrayObj->EdgeFlag); } /* _MaxElement is one past the last legal array element */ @@ -548,7 +582,7 @@ _mesa_update_state_locked( GLcontext *ctx ) if (new_state & _DD_NEW_SEPARATE_SPECULAR) update_separate_specular( ctx ); - if (new_state & (_NEW_ARRAY | _NEW_PROGRAM)) + if (new_state & (_NEW_ARRAY | _NEW_PROGRAM | _NEW_BUFFER_OBJECT)) update_arrays( ctx ); if (new_state & (_NEW_BUFFERS | _NEW_VIEWPORT)) diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c index 527555be0e4..4d153b1c0b2 100644 --- a/src/mesa/main/varray.c +++ b/src/mesa/main/varray.c @@ -65,22 +65,9 @@ update_array(GLcontext *ctx, struct gl_client_array *array, array->Ptr = (const GLubyte *) ptr; array->_ElementSize = elementSize; -#if FEATURE_ARB_vertex_buffer_object _mesa_reference_buffer_object(ctx, &array->BufferObj, ctx->Array.ArrayBufferObj); - /* Compute the index of the last array element that's inside the buffer. - * Later in glDrawArrays we'll check if start + count > _MaxElement to - * be sure we won't go out of bounds. - */ - if (array->BufferObj->Name) - array->_MaxElement = ((GLsizeiptrARB) array->BufferObj->Size - - (GLsizeiptrARB) array->Ptr + array->StrideB - - elementSize) / array->StrideB; - else -#endif - array->_MaxElement = 2 * 1000 * 1000 * 1000; /* just a big number */ - ctx->NewState |= _NEW_ARRAY; ctx->Array.NewState |= dirtyBit; } -- 2.30.2