diff options
| author | Brian Paul <brianp@vmware.com> | 2009-05-06 15:17:25 -0600 | 
|---|---|---|
| committer | Brian Paul <brianp@vmware.com> | 2009-05-07 10:12:33 -0600 | 
| commit | b9d0f947f2bcc47047b162e3d7c8f91b6153e02c (patch) | |
| tree | 44ece271963c4792f87d690da436a6555ea32463 /src | |
| parent | 800b14cd378ed708a29230d92031ac7b6ad6a286 (diff) | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/mesa/main/bufferobj.c | 2 | ||||
| -rw-r--r-- | src/mesa/main/mtypes.h | 1 | ||||
| -rw-r--r-- | src/mesa/main/state.c | 88 | ||||
| -rw-r--r-- | 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 c8d160baa9..49f690ddd2 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!  <data> may be null! */ diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 716e5c655d..368acde7a1 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 47e1aaa728..a6411f7b62 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 527555be0e..4d153b1c0b 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;  }  | 
