/**
* 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,
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 =
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;
}
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;
}
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;
* 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",
}
+/**
+ * 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).
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",
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);
}
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",
return;
}
-#if 0 /* debug */
- check_draw_arrays_data(ctx, start, count);
-#endif
+ if (0)
+ check_draw_arrays_data(ctx, start, count);
- bind_arrays( ctx );
+ vbo_draw_arrays(ctx, mode, start, count, primcount);
- /* 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;
-
- vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL,
- GL_TRUE, start, start + count - 1 );
-
-#if 0 /* debug */
- print_draw_arrays(ctx, exec, mode, start, count);
-#endif
+ if (0)
+ print_draw_arrays(ctx, mode, start, count);
}
/* 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++) {