diff options
Diffstat (limited to 'src/mesa')
| -rw-r--r-- | src/mesa/vbo/vbo_exec_api.c | 23 | ||||
| -rw-r--r-- | src/mesa/vbo/vbo_exec_array.c | 236 | ||||
| -rw-r--r-- | src/mesa/vbo/vbo_save_api.c | 13 | 
3 files changed, 186 insertions, 86 deletions
diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c index 80ca1d866e..1ef4917419 100644 --- a/src/mesa/vbo/vbo_exec_api.c +++ b/src/mesa/vbo/vbo_exec_api.c @@ -568,6 +568,28 @@ static void GLAPIENTRY vbo_exec_End( void )  } +/** + * Called via glPrimitiveRestartNV() + */ +static void GLAPIENTRY +vbo_exec_PrimitiveRestartNV(void) +{ +   GLenum curPrim; +   GET_CURRENT_CONTEXT( ctx );  + +   curPrim = ctx->Driver.CurrentExecPrimitive; + +   if (curPrim == PRIM_OUTSIDE_BEGIN_END) { +      _mesa_error( ctx, GL_INVALID_OPERATION, "glPrimitiveRestartNV" ); +   } +   else { +      vbo_exec_End(); +      vbo_exec_Begin(curPrim); +   } +} + + +  static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec )  {     GLvertexformat *vfmt = &exec->vtxfmt; @@ -576,6 +598,7 @@ static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec )     vfmt->Begin = vbo_exec_Begin;     vfmt->End = vbo_exec_End; +   vfmt->PrimitiveRestartNV = vbo_exec_PrimitiveRestartNV;     _MESA_INIT_DLIST_VTXFMT(vfmt, _mesa_);     _MESA_INIT_EVAL_VTXFMT(vfmt, vbo_exec_); diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c index f46ba636fe..dd36cc32a7 100644 --- a/src/mesa/vbo/vbo_exec_array.c +++ b/src/mesa/vbo/vbo_exec_array.c @@ -41,6 +41,8 @@  /**   * Compute min and max elements by scanning the index buffer for   * glDraw[Range]Elements() calls. + * If primitive restart is enabled, we need to ignore restart + * indexes when computing min/max.   */  void  vbo_get_minmax_index(struct gl_context *ctx, @@ -48,9 +50,11 @@ vbo_get_minmax_index(struct gl_context *ctx,  		     const struct _mesa_index_buffer *ib,  		     GLuint *min_index, GLuint *max_index)  { -   GLuint i; -   GLuint count = prim->count; +   const GLboolean restart = ctx->Array.PrimitiveRestart; +   const GLuint restartIndex = ctx->Array.RestartIndex; +   const GLuint count = prim->count;     const void *indices; +   GLuint i;     if (_mesa_is_bufferobj(ib->obj)) {        const GLvoid *map = @@ -64,11 +68,21 @@ vbo_get_minmax_index(struct gl_context *ctx,     switch (ib->type) {     case GL_UNSIGNED_INT: {        const GLuint *ui_indices = (const GLuint *)indices; -      GLuint max_ui = ui_indices[count-1]; -      GLuint min_ui = ui_indices[0]; -      for (i = 0; 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]; +      GLuint max_ui = 0; +      GLuint min_ui = ~0U; +      if (restart) { +         for (i = 0; i < count; i++) { +            if (ui_indices[i] != restartIndex) { +               if (ui_indices[i] > max_ui) max_ui = ui_indices[i]; +               if (ui_indices[i] < min_ui) min_ui = ui_indices[i]; +            } +         } +      } +      else { +         for (i = 0; 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; @@ -76,11 +90,21 @@ vbo_get_minmax_index(struct gl_context *ctx,     }     case GL_UNSIGNED_SHORT: {        const GLushort *us_indices = (const GLushort *)indices; -      GLuint max_us = us_indices[count-1]; -      GLuint min_us = us_indices[0]; -      for (i = 0; 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]; +      GLuint max_us = 0; +      GLuint min_us = ~0U; +      if (restart) { +         for (i = 0; i < count; i++) { +            if (us_indices[i] != restartIndex) { +               if (us_indices[i] > max_us) max_us = us_indices[i]; +               if (us_indices[i] < min_us) min_us = us_indices[i]; +            } +         } +      } +      else { +         for (i = 0; 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; @@ -88,11 +112,21 @@ vbo_get_minmax_index(struct gl_context *ctx,     }     case GL_UNSIGNED_BYTE: {        const GLubyte *ub_indices = (const GLubyte *)indices; -      GLuint max_ub = ub_indices[count-1]; -      GLuint min_ub = ub_indices[0]; -      for (i = 0; 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]; +      GLuint max_ub = 0; +      GLuint min_ub = ~0U; +      if (restart) { +         for (i = 0; i < count; i++) { +            if (ub_indices[i] != restartIndex) { +               if (ub_indices[i] > max_ub) max_ub = ub_indices[i]; +               if (ub_indices[i] < min_ub) min_ub = ub_indices[i]; +            } +         } +      } +      else { +         for (i = 0; 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; @@ -254,9 +288,11 @@ check_draw_arrays_data(struct gl_context *ctx, GLint start, GLsizei count)   * Print info/data for glDrawArrays(), for debugging.   */  static void -print_draw_arrays(struct gl_context *ctx, struct vbo_exec_context *exec, +print_draw_arrays(struct gl_context *ctx,                    GLenum mode, GLint start, GLsizei count)  { +   struct vbo_context *vbo = vbo_context(ctx); +   struct vbo_exec_context *exec = &vbo->exec;     int i;     printf("vbo_exec_DrawArrays(mode 0x%x, start %d, count %d):\n", @@ -471,6 +507,90 @@ bind_arrays(struct gl_context *ctx)  } +/** + * Helper function called by the other DrawArrays() functions below. + * This is where we handle primitive restart for drawing non-indexed + * arrays.  If primitive restart is enabled, it typically means + * splitting one DrawArrays() into two. + */ +static void +vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start, +                GLsizei count, GLuint numInstances) +{ +   struct vbo_context *vbo = vbo_context(ctx); +   struct vbo_exec_context *exec = &vbo->exec; +   struct _mesa_prim prim[2]; + +   bind_arrays(ctx); + +   /* Again... because we may have changed the bitmask of per-vertex varying +    * attributes.  If we regenerate the fixed-function vertex program now +    * we may be able to prune down the number of vertex attributes which we +    * need in the shader. +    */ +   if (ctx->NewState) +      _mesa_update_state(ctx); + +   prim[0].begin = 1; +   prim[0].end = 1; +   prim[0].weak = 0; +   prim[0].pad = 0; +   prim[0].mode = mode; +   prim[0].start = 0; /* filled in below */ +   prim[0].count = 0; /* filled in below */ +   prim[0].indexed = 0; +   prim[0].basevertex = 0; +   prim[0].num_instances = numInstances; + +   /* Implement the primitive restart index */ +   if (ctx->Array.PrimitiveRestart && ctx->Array.RestartIndex < count) { +      GLuint primCount = 0; + +      if (ctx->Array.RestartIndex == start) { +         /* special case: RestartIndex at beginning */ +         if (count > 1) { +            prim[0].start = start + 1; +            prim[0].count = count - 1; +            primCount = 1; +         } +      } +      else if (ctx->Array.RestartIndex == start + count - 1) { +         /* special case: RestartIndex at end */ +         if (count > 1) { +            prim[0].start = start; +            prim[0].count = count - 1; +            primCount = 1; +         } +      } +      else { +         /* general case: RestartIndex in middle, split into two prims */ +         prim[0].start = start; +         prim[0].count = ctx->Array.RestartIndex - start; + +         prim[1] = prim[0]; +         prim[1].start = ctx->Array.RestartIndex + 1; +         prim[1].count = count - prim[1].start; + +         primCount = 2; +      } + +      if (primCount > 0) { +         /* draw one or two prims */ +         vbo->draw_prims(ctx, exec->array.inputs, prim, primCount, NULL, +                         GL_TRUE, start, start + count - 1); +      } +   } +   else { +      /* no prim restart */ +      prim[0].start = start; +      prim[0].count = count; + +      vbo->draw_prims(ctx, exec->array.inputs, prim, 1, NULL, +                      GL_TRUE, start, start + count - 1); +   } +} + +  /**   * Called from glDrawArrays when in immediate mode (not display list mode). @@ -479,9 +599,6 @@ static void GLAPIENTRY  vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)  {     GET_CURRENT_CONTEXT(ctx); -   struct vbo_context *vbo = vbo_context(ctx); -   struct vbo_exec_context *exec = &vbo->exec; -   struct _mesa_prim prim[1];     if (MESA_VERBOSE & VERBOSE_DRAW)        _mesa_debug(ctx, "glDrawArrays(%s, %d, %d)\n", @@ -496,41 +613,13 @@ vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)        return;     } -#if 0 -   check_draw_arrays_data(ctx, start, count); -#else -   (void) check_draw_arrays_data; -#endif - -   bind_arrays( ctx ); - -   /* Again... because we may have changed the bitmask of per-vertex varying -    * attributes.  If we regenerate the fixed-function vertex program now -    * we may be able to prune down the number of vertex attributes which we -    * need in the shader. -    */ -   if (ctx->NewState) -      _mesa_update_state( ctx ); - -   prim[0].begin = 1; -   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; -   prim[0].basevertex = 0; -   prim[0].num_instances = 1; +   if (0) +      check_draw_arrays_data(ctx, start, count); -   vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, -                    GL_TRUE, start, start + count - 1 ); +   vbo_draw_arrays(ctx, mode, start, count, 1); -#if 0 -   print_draw_arrays(ctx, exec, mode, start, count); -#else -   (void) print_draw_arrays; -#endif +   if (0) +      print_draw_arrays(ctx, mode, start, count);  } @@ -543,9 +632,6 @@ vbo_exec_DrawArraysInstanced(GLenum mode, GLint start, GLsizei count,                               GLsizei primcount)  {     GET_CURRENT_CONTEXT(ctx); -   struct vbo_context *vbo = vbo_context(ctx); -   struct vbo_exec_context *exec = &vbo->exec; -   struct _mesa_prim prim[1];     if (MESA_VERBOSE & VERBOSE_DRAW)        _mesa_debug(ctx, "glDrawArraysInstanced(%s, %d, %d, %d)\n", @@ -560,37 +646,13 @@ vbo_exec_DrawArraysInstanced(GLenum mode, GLint start, GLsizei count,        return;     } -#if 0 /* debug */ -   check_draw_arrays_data(ctx, start, count); -#endif - -   bind_arrays( ctx ); - -   /* Again... because we may have changed the bitmask of per-vertex varying -    * attributes.  If we regenerate the fixed-function vertex program now -    * we may be able to prune down the number of vertex attributes which we -    * need in the shader. -    */ -   if (ctx->NewState) -      _mesa_update_state( ctx ); - -   prim[0].begin = 1; -   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; -   prim[0].basevertex = 0; -   prim[0].num_instances = primcount; +   if (0) +      check_draw_arrays_data(ctx, start, count); -   vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, -                    GL_TRUE, start, start + count - 1 ); +   vbo_draw_arrays(ctx, mode, start, count, primcount); -#if 0 /* debug */ -   print_draw_arrays(ctx, exec, mode, start, count); -#endif +   if (0) +      print_draw_arrays(ctx, mode, start, count);  } @@ -1003,6 +1065,8 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,     /* Check if we can handle this thing as a bunch of index offsets from the      * same index pointer.  If we can't, then we have to fall back to doing      * a draw_prims per primitive. +    * Check that the difference between each prim's indexes is a multiple of +    * the index/element size.      */     if (index_type_size != 1) {        for (i = 0; i < primcount; i++) { diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c index 8d66e14ab3..19c4b15d5f 100644 --- a/src/mesa/vbo/vbo_save_api.c +++ b/src/mesa/vbo/vbo_save_api.c @@ -896,6 +896,18 @@ static void GLAPIENTRY _save_Begin( GLenum mode )  } +static void GLAPIENTRY _save_PrimitiveRestartNV( void ) +{ +   GLenum curPrim; +   GET_CURRENT_CONTEXT( ctx );  + +   curPrim = ctx->Driver.CurrentSavePrimitive; + +   _save_End(); +   _save_Begin(curPrim); +} + +  /* Unlike the functions above, these are to be hooked into the vtxfmt   * maintained in ctx->ListState, active when the list is known or   * suspected to be outside any begin/end primitive. @@ -1003,6 +1015,7 @@ static void _save_vtxfmt_init( struct gl_context *ctx )     vfmt->Color4fv = _save_Color4fv;     vfmt->EdgeFlag = _save_EdgeFlag;     vfmt->End = _save_End; +   vfmt->PrimitiveRestartNV = _save_PrimitiveRestartNV;     vfmt->FogCoordfEXT = _save_FogCoordfEXT;     vfmt->FogCoordfvEXT = _save_FogCoordfvEXT;     vfmt->Indexf = _save_Indexf;  | 
