GLuint *min_index, GLuint *max_index,
const GLuint count)
{
- const GLboolean restart = ctx->Array.PrimitiveRestart;
- const GLuint restartIndex = ctx->Array.RestartIndex;
+ const GLboolean restart = ctx->Array._PrimitiveRestart;
+ const GLuint restartIndex = ctx->Array._RestartIndex;
const int index_size = vbo_sizeof_ib_type(ib->type);
const char *indices;
GLuint i;
}
for (i = 0; i < MAT_ATTRIB_MAX; i++) {
- inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->mat_currval[i];
+ inputs[VERT_ATTRIB_GENERIC(i)] =
+ &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT+i];
const_inputs |= VERT_BIT_GENERIC(i);
}
* slots:
*/
for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_GENERIC_MAX; i++) {
- inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->generic_currval[i];
+ inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->currval[VBO_ATTRIB_GENERIC0+i];
const_inputs |= VERT_BIT_GENERIC(i);
}
-
- /* There is no need to make _NEW_ARRAY dirty here for the TnL program,
- * because it already takes care of invalidating the state necessary
- * to revalidate vertex arrays. Not marking the state as dirty also
- * improves performance (quite significantly in some apps).
- */
- if (!ctx->VertexProgram._MaintainTnlProgram)
- ctx->NewState |= _NEW_ARRAY;
- break;
-
- case VP_NV:
- /* NV_vertex_program - attribute arrays alias and override
- * conventional, legacy arrays. No materials, and the generic
- * slots are vacant.
- */
- for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) {
- if (i < VERT_ATTRIB_GENERIC_MAX
- && vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
- inputs[i] = &vertexAttrib[VERT_ATTRIB_GENERIC(i)];
- else if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled)
- inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)];
- else {
- inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i];
- const_inputs |= VERT_BIT_FF(i);
- }
- }
-
- /* Could use just about anything, just to fill in the empty
- * slots:
- */
- for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) {
- inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->generic_currval[i];
- const_inputs |= VERT_BIT_GENERIC(i);
- }
-
- ctx->NewState |= _NEW_ARRAY;
break;
case VP_ARB:
if (vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
inputs[VERT_ATTRIB_GENERIC(i)] = &vertexAttrib[VERT_ATTRIB_GENERIC(i)];
else {
- inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->generic_currval[i];
+ inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->currval[VBO_ATTRIB_GENERIC0+i];
const_inputs |= VERT_BIT_GENERIC(i);
}
}
inputs[VERT_ATTRIB_GENERIC0] = inputs[0];
- ctx->NewState |= _NEW_ARRAY;
break;
}
_mesa_set_varying_vp_inputs( ctx, VERT_BIT_ALL & (~const_inputs) );
+ ctx->NewDriverState |= ctx->DriverFlags.NewArray;
}
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
- vbo_draw_method(exec, DRAW_ARRAYS);
+ vbo_draw_method(vbo, DRAW_ARRAYS);
if (exec->array.recalculate_inputs) {
recalculate_input_bindings(ctx);
}
+/**
+ * Handle a draw case that potentially has primitive restart enabled.
+ *
+ * If primitive restart is enabled, and PrimitiveRestartInSoftware is
+ * set, then vbo_sw_primitive_restart is used to handle the primitive
+ * restart case in software.
+ */
+static void
+vbo_handle_primitive_restart(struct gl_context *ctx,
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLboolean index_bounds_valid,
+ GLuint min_index,
+ GLuint max_index)
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+
+ if ((ib != NULL) &&
+ ctx->Const.PrimitiveRestartInSoftware &&
+ ctx->Array._PrimitiveRestart) {
+ /* Handle primitive restart in software */
+ vbo_sw_primitive_restart(ctx, prim, nr_prims, ib);
+ } else {
+ /* Call driver directly for draw_prims */
+ vbo->draw_prims(ctx, prim, nr_prims, ib,
+ index_bounds_valid, min_index, max_index, NULL);
+ }
+}
+
+
/**
* Helper function called by the other DrawArrays() functions below.
* This is where we handle primitive restart for drawing non-indexed
*/
static void
vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
- GLsizei count, GLuint numInstances)
+ GLsizei count, GLuint numInstances, GLuint baseInstance)
{
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
prim[0].end = 1;
prim[0].mode = mode;
prim[0].num_instances = numInstances;
+ prim[0].base_instance = baseInstance;
/* Implement the primitive restart index */
- if (ctx->Array.PrimitiveRestart && ctx->Array.RestartIndex < count) {
+ if (ctx->Array._PrimitiveRestart && ctx->Array._RestartIndex < count) {
GLuint primCount = 0;
- if (ctx->Array.RestartIndex == start) {
+ if (ctx->Array._RestartIndex == start) {
/* special case: RestartIndex at beginning */
if (count > 1) {
prim[0].start = start + 1;
primCount = 1;
}
}
- else if (ctx->Array.RestartIndex == start + count - 1) {
+ else if (ctx->Array._RestartIndex == start + count - 1) {
/* special case: RestartIndex at end */
if (count > 1) {
prim[0].start = start;
else {
/* general case: RestartIndex in middle, split into two prims */
prim[0].start = start;
- prim[0].count = ctx->Array.RestartIndex - start;
+ prim[0].count = ctx->Array._RestartIndex - start;
prim[1] = prim[0];
- prim[1].start = ctx->Array.RestartIndex + 1;
+ prim[1].start = ctx->Array._RestartIndex + 1;
prim[1].count = count - prim[1].start;
primCount = 2;
if (primCount > 0) {
/* draw one or two prims */
check_buffers_are_unmapped(exec->array.inputs);
- vbo->draw_prims(ctx, exec->array.inputs, prim, primCount, NULL,
+ vbo->draw_prims(ctx, prim, primCount, NULL,
GL_TRUE, start, start + count - 1, NULL);
}
}
prim[0].count = count;
check_buffers_are_unmapped(exec->array.inputs);
- vbo->draw_prims(ctx, exec->array.inputs, prim, 1, NULL,
+ vbo->draw_prims(ctx, prim, 1, NULL,
GL_TRUE, start, start + count - 1,
NULL);
}
+
+ if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
+ _mesa_flush(ctx);
+ }
}
if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
return;
- FLUSH_CURRENT( ctx, 0 );
-
if (0)
check_draw_arrays_data(ctx, start, count);
- vbo_draw_arrays(ctx, mode, start, count, 1);
+ vbo_draw_arrays(ctx, mode, start, count, 1, 0);
if (0)
print_draw_arrays(ctx, mode, start, count);
if (!_mesa_validate_DrawArraysInstanced(ctx, mode, start, count, numInstances))
return;
- FLUSH_CURRENT( ctx, 0 );
-
if (0)
check_draw_arrays_data(ctx, start, count);
- vbo_draw_arrays(ctx, mode, start, count, numInstances);
+ vbo_draw_arrays(ctx, mode, start, count, numInstances, 0);
if (0)
print_draw_arrays(ctx, mode, start, count);
}
+/**
+ * Called from glDrawArraysInstancedBaseInstance when in immediate mode.
+ */
+static void GLAPIENTRY
+vbo_exec_DrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count,
+ GLsizei numInstances, GLuint baseInstance)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_DRAW)
+ _mesa_debug(ctx, "glDrawArraysInstancedBaseInstance(%s, %d, %d, %d, %d)\n",
+ _mesa_lookup_enum_by_nr(mode), first, count,
+ numInstances, baseInstance);
+
+ if (!_mesa_validate_DrawArraysInstanced(ctx, mode, first, count,
+ numInstances))
+ return;
+
+ if (0)
+ check_draw_arrays_data(ctx, first, count);
+
+ vbo_draw_arrays(ctx, mode, first, count, numInstances, baseInstance);
+
+ if (0)
+ print_draw_arrays(ctx, mode, first, count);
+}
+
+
+
/**
* Map GL_ELEMENT_ARRAY_BUFFER and print contents.
* For debugging.
GLuint start, GLuint end,
GLsizei count, GLenum type,
const GLvoid *indices,
- GLint basevertex, GLint numInstances)
+ GLint basevertex, GLuint numInstances,
+ GLuint baseInstance)
{
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
struct _mesa_index_buffer ib;
struct _mesa_prim prim[1];
- FLUSH_CURRENT( ctx, 0 );
-
vbo_bind_arrays(ctx);
ib.count = count;
prim[0].indexed = 1;
prim[0].basevertex = basevertex;
prim[0].num_instances = numInstances;
+ prim[0].base_instance = baseInstance;
/* Need to give special consideration to rendering a range of
* indices starting somewhere above zero. Typically the
*/
check_buffers_are_unmapped(exec->array.inputs);
- vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib,
- index_bounds_valid, start, end, NULL );
+ vbo_handle_primitive_restart(ctx, prim, 1, &ib,
+ index_bounds_valid, start, end);
+
+ if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
+ _mesa_flush(ctx);
+ }
}
#endif
vbo_validated_drawrangeelements(ctx, mode, index_bounds_valid, start, end,
- count, type, indices, basevertex, 1);
+ count, type, indices, basevertex, 1, 0);
}
return;
vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
- count, type, indices, 0, 1);
+ count, type, indices, 0, 1, 0);
}
return;
vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
- count, type, indices, basevertex, 1);
+ count, type, indices, basevertex, 1, 0);
}
return;
vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
- count, type, indices, 0, numInstances);
+ count, type, indices, 0, numInstances, 0);
}
+
/**
* Called by glDrawElementsInstancedBaseVertex() in immediate mode.
*/
return;
vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
- count, type, indices, basevertex, numInstances);
+ count, type, indices, basevertex, numInstances, 0);
+}
+
+
+/**
+ * Called by glDrawElementsInstancedBaseInstance() in immediate mode.
+ */
+static void GLAPIENTRY
+vbo_exec_DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices, GLsizei numInstances,
+ GLuint baseInstance)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_DRAW)
+ _mesa_debug(ctx, "glDrawElementsInstancedBaseInstance(%s, %d, %s, %p, %d, %d)\n",
+ _mesa_lookup_enum_by_nr(mode), count,
+ _mesa_lookup_enum_by_nr(type), indices,
+ numInstances, baseInstance);
+
+ if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
+ numInstances, 0))
+ return;
+
+ vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
+ count, type, indices, 0, numInstances,
+ baseInstance);
+}
+
+
+/**
+ * Called by glDrawElementsInstancedBaseVertexBaseInstance() in immediate mode.
+ */
+static void GLAPIENTRY
+vbo_exec_DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices, GLsizei numInstances,
+ GLint basevertex, GLuint baseInstance)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_DRAW)
+ _mesa_debug(ctx, "glDrawElementsInstancedBaseVertexBaseInstance(%s, %d, %s, %p, %d, %d, %d)\n",
+ _mesa_lookup_enum_by_nr(mode), count,
+ _mesa_lookup_enum_by_nr(type), indices,
+ numInstances, basevertex, baseInstance);
+
+ if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
+ numInstances, basevertex))
+ return;
+
+ vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
+ count, type, indices, basevertex, numInstances,
+ baseInstance);
}
static void
vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
const GLsizei *count, GLenum type,
- const GLvoid **indices, GLsizei primcount,
+ const GLvoid * const *indices,
+ GLsizei primcount,
const GLint *basevertex)
{
struct vbo_context *vbo = vbo_context(ctx);
if (primcount == 0)
return;
- FLUSH_CURRENT( ctx, 0 );
-
prim = calloc(1, primcount * sizeof(*prim));
if (prim == NULL) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements");
prim[i].count = count[i];
prim[i].indexed = 1;
prim[i].num_instances = 1;
+ prim[i].base_instance = 0;
if (basevertex != NULL)
prim[i].basevertex = basevertex[i];
else
}
check_buffers_are_unmapped(exec->array.inputs);
- vbo->draw_prims(ctx, exec->array.inputs, prim, primcount, &ib,
- GL_FALSE, ~0, ~0, NULL);
+ vbo_handle_primitive_restart(ctx, prim, primcount, &ib,
+ GL_FALSE, ~0, ~0);
} else {
/* render one prim at a time */
for (i = 0; i < primcount; i++) {
prim[0].count = count[i];
prim[0].indexed = 1;
prim[0].num_instances = 1;
+ prim[0].base_instance = 0;
if (basevertex != NULL)
prim[0].basevertex = basevertex[i];
else
prim[0].basevertex = 0;
check_buffers_are_unmapped(exec->array.inputs);
- vbo->draw_prims(ctx, exec->array.inputs, prim, 1, &ib,
- GL_FALSE, ~0, ~0, NULL);
+ vbo_handle_primitive_restart(ctx, prim, 1, &ib,
+ GL_FALSE, ~0, ~0);
}
}
free(prim);
+
+ if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
+ _mesa_flush(ctx);
+ }
}
GLsizei primcount)
{
GET_CURRENT_CONTEXT(ctx);
- GLint i;
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- for (i = 0; i < primcount; i++) {
- if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i],
- 0))
- return;
- }
+ if (!_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices,
+ primcount, NULL))
+ return;
vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
NULL);
static void GLAPIENTRY
vbo_exec_MultiDrawElementsBaseVertex(GLenum mode,
const GLsizei *count, GLenum type,
- const GLvoid **indices,
+ const GLvoid * const *indices,
GLsizei primcount,
const GLsizei *basevertex)
{
GET_CURRENT_CONTEXT(ctx);
- GLint i;
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- for (i = 0; i < primcount; i++) {
- if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i],
- basevertex[i]))
- return;
- }
+ if (!_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices,
+ primcount, basevertex))
+ return;
vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
basevertex);
}
-#if FEATURE_EXT_transform_feedback
-
static void
vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
struct gl_transform_feedback_object *obj,
- GLuint numInstances)
+ GLuint stream, GLuint numInstances)
{
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
struct _mesa_prim prim[2];
+ if (!_mesa_validate_DrawTransformFeedback(ctx, mode, obj, stream,
+ numInstances)) {
+ return;
+ }
+
vbo_bind_arrays(ctx);
/* init most fields to zero */
prim[0].end = 1;
prim[0].mode = mode;
prim[0].num_instances = numInstances;
+ prim[0].base_instance = 0;
/* Maybe we should do some primitive splitting for primitive restart
* (like in DrawArrays), but we have no way to know how many vertices
* will be rendered. */
check_buffers_are_unmapped(exec->array.inputs);
- vbo->draw_prims(ctx, exec->array.inputs, prim, 1, NULL,
+ vbo->draw_prims(ctx, prim, 1, NULL,
GL_TRUE, 0, 0, obj);
+
+ if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
+ _mesa_flush(ctx);
+ }
}
/**
_mesa_debug(ctx, "glDrawTransformFeedback(%s, %d)\n",
_mesa_lookup_enum_by_nr(mode), name);
- if (!_mesa_validate_DrawTransformFeedback(ctx, mode, obj)) {
- return;
- }
+ vbo_draw_transform_feedback(ctx, mode, obj, 0, 1);
+}
+
+static void GLAPIENTRY
+vbo_exec_DrawTransformFeedbackStream(GLenum mode, GLuint name, GLuint stream)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_transform_feedback_object *obj =
+ _mesa_lookup_transform_feedback_object(ctx, name);
- FLUSH_CURRENT(ctx, 0);
+ if (MESA_VERBOSE & VERBOSE_DRAW)
+ _mesa_debug(ctx, "glDrawTransformFeedbackStream(%s, %u, %u)\n",
+ _mesa_lookup_enum_by_nr(mode), name, stream);
- vbo_draw_transform_feedback(ctx, mode, obj, 1);
+ vbo_draw_transform_feedback(ctx, mode, obj, stream, 1);
}
-#endif
+static void GLAPIENTRY
+vbo_exec_DrawTransformFeedbackInstanced(GLenum mode, GLuint name,
+ GLsizei primcount)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_transform_feedback_object *obj =
+ _mesa_lookup_transform_feedback_object(ctx, name);
+
+ if (MESA_VERBOSE & VERBOSE_DRAW)
+ _mesa_debug(ctx, "glDrawTransformFeedbackInstanced(%s, %d)\n",
+ _mesa_lookup_enum_by_nr(mode), name);
+
+ vbo_draw_transform_feedback(ctx, mode, obj, 0, primcount);
+}
+
+static void GLAPIENTRY
+vbo_exec_DrawTransformFeedbackStreamInstanced(GLenum mode, GLuint name,
+ GLuint stream, GLsizei primcount)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_transform_feedback_object *obj =
+ _mesa_lookup_transform_feedback_object(ctx, name);
+
+ if (MESA_VERBOSE & VERBOSE_DRAW)
+ _mesa_debug(ctx, "glDrawTransformFeedbackStreamInstanced"
+ "(%s, %u, %u, %i)\n",
+ _mesa_lookup_enum_by_nr(mode), name, stream, primcount);
+
+ vbo_draw_transform_feedback(ctx, mode, obj, stream, primcount);
+}
/**
* Plug in the immediate-mode vertex array drawing commands into the
exec->vtxfmt.DrawRangeElementsBaseVertex = vbo_exec_DrawRangeElementsBaseVertex;
exec->vtxfmt.MultiDrawElementsBaseVertex = vbo_exec_MultiDrawElementsBaseVertex;
exec->vtxfmt.DrawArraysInstanced = vbo_exec_DrawArraysInstanced;
+ exec->vtxfmt.DrawArraysInstancedBaseInstance = vbo_exec_DrawArraysInstancedBaseInstance;
exec->vtxfmt.DrawElementsInstanced = vbo_exec_DrawElementsInstanced;
+ exec->vtxfmt.DrawElementsInstancedBaseInstance = vbo_exec_DrawElementsInstancedBaseInstance;
exec->vtxfmt.DrawElementsInstancedBaseVertex = vbo_exec_DrawElementsInstancedBaseVertex;
-#if FEATURE_EXT_transform_feedback
+ exec->vtxfmt.DrawElementsInstancedBaseVertexBaseInstance = vbo_exec_DrawElementsInstancedBaseVertexBaseInstance;
exec->vtxfmt.DrawTransformFeedback = vbo_exec_DrawTransformFeedback;
-#endif
+ exec->vtxfmt.DrawTransformFeedbackStream =
+ vbo_exec_DrawTransformFeedbackStream;
+ exec->vtxfmt.DrawTransformFeedbackInstanced =
+ vbo_exec_DrawTransformFeedbackInstanced;
+ exec->vtxfmt.DrawTransformFeedbackStreamInstanced =
+ vbo_exec_DrawTransformFeedbackStreamInstanced;
}
primcount, basevertex);
}
-#if FEATURE_EXT_transform_feedback
-
void GLAPIENTRY
_mesa_DrawTransformFeedback(GLenum mode, GLuint name)
{
vbo_exec_DrawTransformFeedback(mode, name);
}
-
-#endif