[Mesa-dev] [PATCH 1/4] mesa: implement GL_ARB_draw_indirect
Brian Paul
brianp at vmware.com
Thu Apr 4 12:17:07 PDT 2013
I just did a quick skim and found a few minor things.
First, the subject might be "mesa: implement GL_ARB_draw_indirect and
GL_ARB_multi_draw_indirect"
This is a big patch and I think it could have been broken down into
smaller pieces, but I know it's a PITA to redo. Next time.
On 04/04/2013 12:18 PM, Christoph Bumiller wrote:
> ---
> src/mapi/glapi/gen/Makefile.am | 1 +
> src/mapi/glapi/gen/gl_API.xml | 4 +-
> src/mesa/drivers/dri/i965/brw_draw.c | 3 +-
> src/mesa/drivers/dri/i965/brw_draw.h | 3 +-
> src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c | 9 +-
> src/mesa/main/api_validate.c | 159 ++++++++++++++++
> src/mesa/main/api_validate.h | 26 +++
> src/mesa/main/bufferobj.c | 9 +
> src/mesa/main/dd.h | 12 ++
> src/mesa/main/dlist.c | 41 ++++
> src/mesa/main/extensions.c | 2 +
> src/mesa/main/get.c | 5 +
> src/mesa/main/get_hash_params.py | 2 +
> src/mesa/main/mtypes.h | 4 +
> src/mesa/main/tests/dispatch_sanity.cpp | 8 +-
> src/mesa/main/vtxfmt.c | 7 +
> src/mesa/state_tracker/st_cb_rasterpos.c | 2 +-
> src/mesa/state_tracker/st_draw.c | 3 +-
> src/mesa/state_tracker/st_draw.h | 6 +-
> src/mesa/state_tracker/st_draw_feedback.c | 3 +-
> src/mesa/tnl/tnl.h | 3 +-
> src/mesa/vbo/vbo.h | 5 +-
> src/mesa/vbo/vbo_exec_array.c | 255 +++++++++++++++++++++++++-
> src/mesa/vbo/vbo_exec_draw.c | 2 +-
> src/mesa/vbo/vbo_primitive_restart.c | 4 +-
> src/mesa/vbo/vbo_rebase.c | 2 +-
> src/mesa/vbo/vbo_save_api.c | 53 ++++++
> src/mesa/vbo/vbo_save_draw.c | 2 +-
> src/mesa/vbo/vbo_split_copy.c | 2 +-
> src/mesa/vbo/vbo_split_inplace.c | 2 +-
> 30 files changed, 611 insertions(+), 28 deletions(-)
>
> diff --git a/src/mapi/glapi/gen/Makefile.am b/src/mapi/glapi/gen/Makefile.am
> index 36e47e2..243c148 100644
> --- a/src/mapi/glapi/gen/Makefile.am
> +++ b/src/mapi/glapi/gen/Makefile.am
> @@ -96,6 +96,7 @@ API_XML = \
> ARB_depth_clamp.xml \
> ARB_draw_buffers_blend.xml \
> ARB_draw_elements_base_vertex.xml \
> + ARB_draw_indirect.xml \
> ARB_draw_instanced.xml \
> ARB_ES2_compatibility.xml \
> ARB_ES3_compatibility.xml \
> diff --git a/src/mapi/glapi/gen/gl_API.xml b/src/mapi/glapi/gen/gl_API.xml
> index df95924..f22fdac 100644
> --- a/src/mapi/glapi/gen/gl_API.xml
> +++ b/src/mapi/glapi/gen/gl_API.xml
> @@ -8240,6 +8240,8 @@
>
> <!-- ARB extensions #86...#93 -->
>
> +<xi:include href="ARB_draw_indirect.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
> +
> <category name="GL_ARB_transform_feedback3" number="94">
> <enum name="MAX_TRANSFORM_FEEDBACK_BUFFERS" value="0x8E70"/>
> <enum name="MAX_VERTEX_STREAMS" value="0x8E71"/>
> @@ -8317,7 +8319,7 @@
>
> <xi:include href="ARB_invalidate_subdata.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
>
> -<!-- ARB extensions #133...#138 -->
> +<!-- ARB extensions #134...#138 -->
>
> <xi:include href="ARB_texture_buffer_range.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
>
> diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c
> index 809bcc5..d0c8415 100644
> --- a/src/mesa/drivers/dri/i965/brw_draw.c
> +++ b/src/mesa/drivers/dri/i965/brw_draw.c
> @@ -548,7 +548,8 @@ void brw_draw_prims( struct gl_context *ctx,
> GLboolean index_bounds_valid,
> GLuint min_index,
> GLuint max_index,
> - struct gl_transform_feedback_object *tfb_vertcount )
> + struct gl_transform_feedback_object *tfb_vertcount,
> + struct gl_buffer_object *indirect )
> {
> struct intel_context *intel = intel_context(ctx);
> const struct gl_client_array **arrays = ctx->Array._DrawArrays;
> diff --git a/src/mesa/drivers/dri/i965/brw_draw.h b/src/mesa/drivers/dri/i965/brw_draw.h
> index d86a9e7..3dfac2e 100644
> --- a/src/mesa/drivers/dri/i965/brw_draw.h
> +++ b/src/mesa/drivers/dri/i965/brw_draw.h
> @@ -41,7 +41,8 @@ void brw_draw_prims( struct gl_context *ctx,
> GLboolean index_bounds_valid,
> GLuint min_index,
> GLuint max_index,
> - struct gl_transform_feedback_object *tfb_vertcount );
> + struct gl_transform_feedback_object *tfb_vertcount,
> + struct gl_buffer_object *tfb_vertcount );
>
> void brw_draw_init( struct brw_context *brw );
> void brw_draw_destroy( struct brw_context *brw );
> diff --git a/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c b/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c
> index 436db32..4dee0b8 100644
> --- a/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c
> +++ b/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c
> @@ -222,7 +222,8 @@ TAG(vbo_render_prims)(struct gl_context *ctx,
> const struct _mesa_index_buffer *ib,
> GLboolean index_bounds_valid,
> GLuint min_index, GLuint max_index,
> - struct gl_transform_feedback_object *tfb_vertcount);
> + struct gl_transform_feedback_object *tfb_vertcount,
> + struct gl_buffer_object *indirect);
>
> static GLboolean
> vbo_maybe_split(struct gl_context *ctx, const struct gl_client_array **arrays,
> @@ -453,7 +454,8 @@ TAG(vbo_render_prims)(struct gl_context *ctx,
> const struct _mesa_index_buffer *ib,
> GLboolean index_bounds_valid,
> GLuint min_index, GLuint max_index,
> - struct gl_transform_feedback_object *tfb_vertcount)
> + struct gl_transform_feedback_object *tfb_vertcount,
> + struct gl_buffer_object *indirect)
> {
> struct nouveau_render_state *render = to_render_state(ctx);
> const struct gl_client_array **arrays = ctx->Array._DrawArrays;
> @@ -489,7 +491,8 @@ TAG(vbo_check_render_prims)(struct gl_context *ctx,
> const struct _mesa_index_buffer *ib,
> GLboolean index_bounds_valid,
> GLuint min_index, GLuint max_index,
> - struct gl_transform_feedback_object *tfb_vertcount)
> + struct gl_transform_feedback_object *tfb_vertcount,
> + struct gl_buffer_object *indirect)
> {
> struct nouveau_context *nctx = to_nouveau_context(ctx);
>
> diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c
> index 53b0021..db9566c 100644
> --- a/src/mesa/main/api_validate.c
> +++ b/src/mesa/main/api_validate.c
> @@ -737,3 +737,162 @@ _mesa_validate_DrawTransformFeedback(struct gl_context *ctx,
>
> return GL_TRUE;
> }
> +
> +static GLboolean
> +valid_draw_indirect(struct gl_context *ctx,
> + GLenum mode, const GLvoid *indirect,
> + GLsizei size, const char *name)
> +{
> + const GLsizeiptr end = (GLsizeiptr)indirect + size;
> +
> + if (!_mesa_valid_prim_mode(ctx, mode, name))
> + return GL_FALSE;
> +
> + if ((GLsizeiptr)indirect& (sizeof(GLuint) - 1)) {
> + _mesa_error(ctx, GL_INVALID_OPERATION,
> + "%s(indirect is not aligned)", name);
> + return GL_FALSE;
> + }
> +
> + if (_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) {
> + if (_mesa_bufferobj_mapped(ctx->DrawIndirectBuffer)) {
> + _mesa_error(ctx, GL_INVALID_OPERATION,
> + "%s(DRAW_INDIRECT_BUFFER is mapped)", name);
> + return GL_FALSE;
> + }
> + if (ctx->DrawIndirectBuffer->Size< end) {
> + _mesa_error(ctx, GL_INVALID_OPERATION,
> + "%s(DRAW_INDIRECT_BUFFER too small)", name);
> + return GL_FALSE;
> + }
> + } else {
> + if (ctx->API != API_OPENGL_COMPAT) {
> + _mesa_error(ctx, GL_INVALID_OPERATION,
> + "%s: no buffer bound to DRAW_INDIRECT_BUFFER", name);
> + return GL_FALSE;
> + }
> + }
> +
> + if (!check_valid_to_render(ctx, name))
> + return GL_FALSE;
> +
> + return GL_TRUE;
> +}
> +
> +static inline GLboolean
> +valid_draw_indirect_elements(struct gl_context *ctx,
> + GLenum mode, GLenum type, const GLvoid *indirect,
> + GLsizeiptr size, const char *name)
> +{
> + if (!valid_elements_type(ctx, type, name))
> + return GL_FALSE;
> +
> + /*
> + * Unlike regular DrawElementsInstancedBaseVertex commands, the indices
> + * may not come from a client array and must come from an index buffer.
> + * If no element array buffer is bound, * an INVALID_OPERATION error is
Stray '*' in that sentence.
> + * generated.
> + */
> + if (!_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj)) {
> + _mesa_error(ctx, GL_INVALID_OPERATION,
> + "%s(no buffer bound to GL_ELEMENT_ARRAY_BUFFER)", name);
> + return GL_FALSE;
> + }
> +
> + return valid_draw_indirect(ctx, mode, indirect, size, name);
> +}
> +
> +static inline GLboolean
> +valid_draw_indirect_multi(struct gl_context *ctx,
> + GLsizei primcount, GLsizei stride,
> + const char *name)
> +{
> + if (primcount< 0) {
> + _mesa_error(ctx, GL_INVALID_VALUE, "%s(primcount< 0)", name);
> + return GL_FALSE;
> + }
> +
> + if (stride % 4) {
> + _mesa_error(ctx, GL_INVALID_VALUE, "%s(stride %% 4)", name);
> + return GL_FALSE;
> + }
> +
> + return GL_TRUE;
> +}
> +
> +extern GLboolean
rm extern
> +_mesa_validate_DrawArraysIndirect(struct gl_context *ctx,
> + GLenum mode,
> + const GLvoid *indirect)
> +{
> + FLUSH_CURRENT(ctx, 0);
> +
> + if (!valid_draw_indirect(ctx, mode,
> + indirect, 4 * sizeof(GLuint),
> + "glDrawArraysIndirect"))
> + return GL_FALSE;
> +
> + return GL_TRUE;
How about simplifying this to:
return valid_draw_indirect(ctx, mode,
indirect, 4 * sizeof(GLuint),
"glDrawArraysIndirect"))
> +}
> +
> +extern GLboolean
> +_mesa_validate_DrawElementsIndirect(struct gl_context *ctx,
> + GLenum mode, GLenum type,
> + const GLvoid *indirect)
> +{
> + FLUSH_CURRENT(ctx, 0);
> +
> + if (!valid_draw_indirect_elements(ctx, mode, type,
> + indirect, 5 * sizeof(GLuint),
> + "glDrawElementsIndirect"))
> + return GL_FALSE;
> +
> + return GL_TRUE;
> +}
Same as above.
> +
> +extern GLboolean
rm extern
> +_mesa_validate_MultiDrawArraysIndirect(struct gl_context *ctx,
> + GLenum mode,
> + const GLvoid *indirect,
> + GLsizei primcount, GLsizei stride)
> +{
> + GLsizeiptr size = 0;
> + if (primcount)
> + size = (primcount - 1) * stride + 4 * sizeof(GLuint);
> +
> + FLUSH_CURRENT(ctx, 0);
> +
> + if (!valid_draw_indirect_multi(ctx, primcount, stride,
> + "glMultiDrawArraysIndirect"))
> + return GL_FALSE;
> +
> + if (!valid_draw_indirect(ctx, mode, indirect, size,
> + "glMultiDrawArraysIndirect"))
> + return GL_FALSE;
> +
> + return GL_TRUE;
> +}
> +
> +extern GLboolean
rm extern.
> +_mesa_validate_MultiDrawElementsIndirect(struct gl_context *ctx,
> + GLenum mode, GLenum type,
> + const GLvoid *indirect,
> + GLsizei primcount, GLsizei stride)
> +{
> + GLsizeiptr size = 0;
> + if (primcount)
> + size = (primcount - 1) * stride + 5 * sizeof(GLuint);
> +
> + FLUSH_CURRENT(ctx, 0);
> +
> + if (!valid_draw_indirect_multi(ctx, primcount, stride,
> + "glMultiDrawElementsIndirect"))
> + return GL_FALSE;
> +
> + if (!valid_draw_indirect_elements(ctx, mode, type,
> + indirect, size,
> + "glMultiDrawElementsIndirect"))
> + return GL_FALSE;
> +
> + return GL_TRUE;
> +}
> diff --git a/src/mesa/main/api_validate.h b/src/mesa/main/api_validate.h
> index 0ca9c90..38c6efd 100644
> --- a/src/mesa/main/api_validate.h
> +++ b/src/mesa/main/api_validate.h
> @@ -85,5 +85,31 @@ _mesa_validate_DrawTransformFeedback(struct gl_context *ctx,
> GLuint stream,
> GLsizei numInstances);
>
> +extern GLboolean
> +_mesa_validate_DrawArraysIndirect(struct gl_context *ctx,
> + GLenum mode,
> + const GLvoid *indirect);
> +
> +extern GLboolean
> +_mesa_validate_DrawElementsIndirect(struct gl_context *ctx,
> + GLenum mode,
> + GLenum type,
> + const GLvoid *indirect);
> +
> +extern GLboolean
> +_mesa_validate_MultiDrawArraysIndirect(struct gl_context *ctx,
> + GLenum mode,
> + const GLvoid *indirect,
> + GLsizei primcount,
> + GLsizei stride);
> +
> +extern GLboolean
> +_mesa_validate_MultiDrawElementsIndirect(struct gl_context *ctx,
> + GLenum mode,
> + GLenum type,
> + const GLvoid *indirect,
> + GLsizei primcount,
> + GLsizei stride);
> +
>
> #endif
> diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c
> index b82ba7b..0fe01d4 100644
> --- a/src/mesa/main/bufferobj.c
> +++ b/src/mesa/main/bufferobj.c
> @@ -87,6 +87,10 @@ get_buffer_target(struct gl_context *ctx, GLenum target)
> return&ctx->CopyReadBuffer;
> case GL_COPY_WRITE_BUFFER:
> return&ctx->CopyWriteBuffer;
> + case GL_DRAW_INDIRECT_BUFFER:
> + if (ctx->Extensions.ARB_draw_indirect)
> + return&ctx->DrawIndirectBuffer;
> + break;
> case GL_TRANSFORM_FEEDBACK_BUFFER:
> if (ctx->Extensions.EXT_transform_feedback) {
> return&ctx->TransformFeedback.CurrentBuffer;
> @@ -875,6 +879,11 @@ _mesa_DeleteBuffers(GLsizei n, const GLuint *ids)
> _mesa_BindBuffer( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 );
> }
>
> + /* unbind ARB_draw_indirect binding point */
> + if (ctx->DrawIndirectBuffer == bufObj) {
> + _mesa_BindBuffer( GL_DRAW_INDIRECT_BUFFER, 0 );
> + }
> +
> /* unbind ARB_copy_buffer binding points */
> if (ctx->CopyReadBuffer == bufObj) {
> _mesa_BindBuffer( GL_COPY_READ_BUFFER, 0 );
> diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
> index 8f3cd3d..51a78b4 100644
> --- a/src/mesa/main/dd.h
> +++ b/src/mesa/main/dd.h
> @@ -1078,6 +1078,18 @@ typedef struct {
> GLuint name,
> GLuint stream,
> GLsizei primcount);
> + void (GLAPIENTRYP DrawArraysIndirect)(GLenum mode,
> + const GLvoid *indirect);
> + void (GLAPIENTRYP DrawElementsIndirect)(GLenum mode, GLenum type,
> + const GLvoid *indirect);
> + void (GLAPIENTRYP MultiDrawArraysIndirect)(GLenum mode,
> + const GLvoid *indirect,
> + GLsizei primcount,
> + GLsizei stride);
> + void (GLAPIENTRYP MultiDrawElementsIndirect)(GLenum mode, GLenum type,
> + const GLvoid *indirect,
> + GLsizei primcount,
> + GLsizei stride);
> /*@}*/
>
> /**
> diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c
> index 4b20d89..45e7439 100644
> --- a/src/mesa/main/dlist.c
> +++ b/src/mesa/main/dlist.c
> @@ -1356,6 +1356,41 @@ save_DrawElementsInstancedBaseVertexBaseInstance(GLenum mode,
> "glDrawElementsInstancedBaseVertexBaseInstance() during display list compile");
> }
>
> +static void GLAPIENTRY
> +save_DrawArraysIndirect(GLenum mode, const GLvoid *indirect)
> +{
> + GET_CURRENT_CONTEXT(ctx);
> + _mesa_error(ctx, GL_INVALID_OPERATION,
> + "glDrawArraysIndirect() during display list compile");
> +}
Is this specified in the spec? IIRC, if a command isn't supposed to
get compiled into a dlist it's just immediately executed.
> +
> +static void GLAPIENTRY
> +save_DrawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect)
> +{
> + GET_CURRENT_CONTEXT(ctx);
> + _mesa_error(ctx, GL_INVALID_OPERATION,
> + "glDrawElementsIndirect() during display list compile");
> +}
> +
> +static void GLAPIENTRY
> +save_MultiDrawArraysIndirect(GLenum mode, const GLvoid *indirect,
> + GLsizei primcount, GLsizei stride)
> +{
> + GET_CURRENT_CONTEXT(ctx);
> + _mesa_error(ctx, GL_INVALID_OPERATION,
> + "glMultiDrawArraysIndirect() during display list compile");
> +}
> +
> +static void GLAPIENTRY
> +save_MultiDrawElementsIndirect(GLenum mode, GLenum type,
> + const GLvoid *indirect,
> + GLsizei primcount, GLsizei stride)
> +{
> + GET_CURRENT_CONTEXT(ctx);
> + _mesa_error(ctx, GL_INVALID_OPERATION,
> + "glMultiDrawElementsIndirect() during display list compile");
> +}
> +
> static void invalidate_saved_current_state( struct gl_context *ctx )
> {
> GLint i;
> @@ -9620,6 +9655,12 @@ _mesa_save_vtxfmt_init(GLvertexformat * vfmt)
> vfmt->DrawElementsInstancedBaseInstance = save_DrawElementsInstancedBaseInstance;
> vfmt->DrawElementsInstancedBaseVertexBaseInstance = save_DrawElementsInstancedBaseVertexBaseInstance;
>
> + /* GL_ARB_draw_indirect and GL_ARB_multi_draw_indirect */
> + vfmt->DrawArraysIndirect = save_DrawArraysIndirect;
> + vfmt->MultiDrawArraysIndirect = save_MultiDrawArraysIndirect;
> + vfmt->DrawElementsIndirect = save_DrawElementsIndirect;
> + vfmt->MultiDrawElementsIndirect = save_MultiDrawElementsIndirect;
> +
> /* The driver is required to implement these as
> * 1) They can probably do a better job.
> * 2) A lot of new mechanisms would have to be added to this module
> diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c
> index c7f038b..0891d47 100644
> --- a/src/mesa/main/extensions.c
> +++ b/src/mesa/main/extensions.c
> @@ -93,6 +93,7 @@ static const struct extension extension_table[] = {
> { "GL_ARB_draw_buffers", o(dummy_true), GL, 2002 },
> { "GL_ARB_draw_buffers_blend", o(ARB_draw_buffers_blend), GL, 2009 },
> { "GL_ARB_draw_elements_base_vertex", o(ARB_draw_elements_base_vertex), GL, 2009 },
> + { "GL_ARB_draw_indirect", o(ARB_draw_indirect), GLC, 2010 },
> { "GL_ARB_draw_instanced", o(ARB_draw_instanced), GL, 2008 },
> { "GL_ARB_explicit_attrib_location", o(ARB_explicit_attrib_location), GL, 2009 },
> { "GL_ARB_fragment_coord_conventions", o(ARB_fragment_coord_conventions), GL, 2009 },
> @@ -109,6 +110,7 @@ static const struct extension extension_table[] = {
> { "GL_ARB_invalidate_subdata", o(dummy_true), GL, 2012 },
> { "GL_ARB_map_buffer_alignment", o(ARB_map_buffer_alignment), GL, 2011 },
> { "GL_ARB_map_buffer_range", o(ARB_map_buffer_range), GL, 2008 },
> + { "GL_ARB_multi_draw_indirect", o(ARB_multi_draw_indirect), GLC, 2012 },
> { "GL_ARB_multisample", o(dummy_true), GLL, 1994 },
> { "GL_ARB_multitexture", o(dummy_true), GLL, 1998 },
> { "GL_ARB_occlusion_query2", o(ARB_occlusion_query2), GL, 2003 },
> diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c
> index 582ef31..f0f44aa 100644
> --- a/src/mesa/main/get.c
> +++ b/src/mesa/main/get.c
> @@ -356,6 +356,7 @@ EXTRA_EXT(ARB_map_buffer_alignment);
> EXTRA_EXT(ARB_texture_cube_map_array);
> EXTRA_EXT(ARB_texture_buffer_range);
> EXTRA_EXT(ARB_texture_multisample);
> +EXTRA_EXT(ARB_draw_indirect);
>
> static const int
> extra_NV_primitive_restart[] = {
> @@ -853,6 +854,10 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu
> _mesa_problem(ctx, "driver doesn't implement GetTimestamp");
> }
> break;
> + /* GL_ARB_draw_indirect */
> + case GL_DRAW_INDIRECT_BUFFER_BINDING:
> + v->value_int = ctx->DrawIndirectBuffer->Name;
> + break;
> }
> }
>
> diff --git a/src/mesa/main/get_hash_params.py b/src/mesa/main/get_hash_params.py
> index 7d4f7e2..68513dc 100644
> --- a/src/mesa/main/get_hash_params.py
> +++ b/src/mesa/main/get_hash_params.py
> @@ -715,6 +715,8 @@ descriptor=[
> { "apis": ["GL_CORE"], "params": [
> # GL_ARB_texture_buffer_range
> [ "TEXTURE_BUFFER_OFFSET_ALIGNMENT", "CONTEXT_INT(Const.TextureBufferOffsetAlignment), extra_ARB_texture_buffer_range" ],
> +# GL_ARB_draw_indirect
> + [ "DRAW_INDIRECT_BUFFER_BINDING", "LOC_CUSTOM, TYPE_INT, 0, extra_ARB_draw_indirect" ],
> ]}
>
> ]
> diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
> index ace6938..4f64683 100644
> --- a/src/mesa/main/mtypes.h
> +++ b/src/mesa/main/mtypes.h
> @@ -2953,6 +2953,7 @@ struct gl_extensions
> GLboolean ARB_depth_texture;
> GLboolean ARB_draw_buffers_blend;
> GLboolean ARB_draw_elements_base_vertex;
> + GLboolean ARB_draw_indirect;
> GLboolean ARB_draw_instanced;
> GLboolean ARB_fragment_coord_conventions;
> GLboolean ARB_fragment_program;
> @@ -2967,6 +2968,7 @@ struct gl_extensions
> GLboolean ARB_internalformat_query;
> GLboolean ARB_map_buffer_alignment;
> GLboolean ARB_map_buffer_range;
> + GLboolean ARB_multi_draw_indirect;
> GLboolean ARB_occlusion_query;
> GLboolean ARB_occlusion_query2;
> GLboolean ARB_point_sprite;
> @@ -3515,6 +3517,8 @@ struct gl_context
>
> struct gl_transform_feedback_state TransformFeedback;
>
> + struct gl_buffer_object *DrawIndirectBuffer; /**< GL_ARB_draw_indirect */
> +
> struct gl_buffer_object *CopyReadBuffer; /**< GL_ARB_copy_buffer */
> struct gl_buffer_object *CopyWriteBuffer; /**< GL_ARB_copy_buffer */
>
> diff --git a/src/mesa/main/tests/dispatch_sanity.cpp b/src/mesa/main/tests/dispatch_sanity.cpp
> index ffd83fe..dedaef4 100644
> --- a/src/mesa/main/tests/dispatch_sanity.cpp
> +++ b/src/mesa/main/tests/dispatch_sanity.cpp
> @@ -674,8 +674,8 @@ const struct function gl_core_functions_possible[] = {
> { "glVertexAttribP3uiv", 43, -1 },
> { "glVertexAttribP4ui", 43, -1 },
> { "glVertexAttribP4uiv", 43, -1 },
> -// { "glDrawArraysIndirect", 43, -1 }, // XXX: Add to xml
> -// { "glDrawElementsIndirect", 43, -1 }, // XXX: Add to xml
> + { "glDrawArraysIndirect", 43, -1 },
> + { "glDrawElementsIndirect", 43, -1 },
> // { "glUniform1d", 43, -1 }, // XXX: Add to xml
> // { "glUniform2d", 43, -1 }, // XXX: Add to xml
> // { "glUniform3d", 43, -1 }, // XXX: Add to xml
> @@ -884,8 +884,8 @@ const struct function gl_core_functions_possible[] = {
> { "glInvalidateBufferData", 43, -1 },
> { "glInvalidateFramebuffer", 43, -1 },
> { "glInvalidateSubFramebuffer", 43, -1 },
> -// { "glMultiDrawArraysIndirect", 43, -1 }, // XXX: Add to xml
> -// { "glMultiDrawElementsIndirect", 43, -1 }, // XXX: Add to xml
> + { "glMultiDrawArraysIndirect", 43, -1 },
> + { "glMultiDrawElementsIndirect", 43, -1 },
> // { "glGetProgramInterfaceiv", 43, -1 }, // XXX: Add to xml
> // { "glGetProgramResourceIndex", 43, -1 }, // XXX: Add to xml
> // { "glGetProgramResourceName", 43, -1 }, // XXX: Add to xml
> diff --git a/src/mesa/main/vtxfmt.c b/src/mesa/main/vtxfmt.c
> index 8669c40..92a9374 100644
> --- a/src/mesa/main/vtxfmt.c
> +++ b/src/mesa/main/vtxfmt.c
> @@ -147,6 +147,13 @@ install_vtxfmt(struct gl_context *ctx, struct _glapi_table *tab,
> vfmt->DrawTransformFeedbackStreamInstanced);
> }
>
> + if (_mesa_is_desktop_gl(ctx)) {
> + SET_DrawArraysIndirect(tab, vfmt->DrawArraysIndirect);
> + SET_DrawElementsIndirect(tab, vfmt->DrawElementsIndirect);
> + SET_MultiDrawArraysIndirect(tab, vfmt->MultiDrawArraysIndirect);
> + SET_MultiDrawElementsIndirect(tab, vfmt->MultiDrawElementsIndirect);
> + }
> +
> /* Originally for GL_NV_vertex_program, this is also used by dlist.c */
> if (ctx->API == API_OPENGL_COMPAT) {
> SET_VertexAttrib1fNV(tab, vfmt->VertexAttrib1fNV);
> diff --git a/src/mesa/state_tracker/st_cb_rasterpos.c b/src/mesa/state_tracker/st_cb_rasterpos.c
> index 4731f26..778218a1 100644
> --- a/src/mesa/state_tracker/st_cb_rasterpos.c
> +++ b/src/mesa/state_tracker/st_cb_rasterpos.c
> @@ -255,7 +255,7 @@ st_RasterPos(struct gl_context *ctx, const GLfloat v[4])
> * st_feedback_draw_vbo doesn't check for that flag. */
> ctx->Array._DrawArrays = rs->arrays;
> st_feedback_draw_vbo(ctx,&rs->prim, 1, NULL, GL_TRUE, 0, 1,
> - NULL);
> + NULL, NULL);
> ctx->Array._DrawArrays = saved_arrays;
>
> /* restore draw's rasterization stage depending on rendermode */
> diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c
> index bff8d9b..ee1c902 100644
> --- a/src/mesa/state_tracker/st_draw.c
> +++ b/src/mesa/state_tracker/st_draw.c
> @@ -195,7 +195,8 @@ st_draw_vbo(struct gl_context *ctx,
> GLboolean index_bounds_valid,
> GLuint min_index,
> GLuint max_index,
> - struct gl_transform_feedback_object *tfb_vertcount)
> + struct gl_transform_feedback_object *tfb_vertcount,
> + struct gl_buffer_object *indirect)
> {
> struct st_context *st = st_context(ctx);
> struct pipe_index_buffer ibuffer = {0};
> diff --git a/src/mesa/state_tracker/st_draw.h b/src/mesa/state_tracker/st_draw.h
> index 3313fc8..401992c 100644
> --- a/src/mesa/state_tracker/st_draw.h
> +++ b/src/mesa/state_tracker/st_draw.h
> @@ -55,7 +55,8 @@ st_draw_vbo(struct gl_context *ctx,
> GLboolean index_bounds_valid,
> GLuint min_index,
> GLuint max_index,
> - struct gl_transform_feedback_object *tfb_vertcount);
> + struct gl_transform_feedback_object *tfb_vertcount,
> + struct gl_buffer_object *indirect);
>
> extern void
> st_feedback_draw_vbo(struct gl_context *ctx,
> @@ -65,7 +66,8 @@ st_feedback_draw_vbo(struct gl_context *ctx,
> GLboolean index_bounds_valid,
> GLuint min_index,
> GLuint max_index,
> - struct gl_transform_feedback_object *tfb_vertcount);
> + struct gl_transform_feedback_object *tfb_vertcount,
> + struct gl_buffer_object *indirect);
>
> /**
> * When drawing with VBOs, the addresses specified with
> diff --git a/src/mesa/state_tracker/st_draw_feedback.c b/src/mesa/state_tracker/st_draw_feedback.c
> index ae87fb2..5ecd7a5 100644
> --- a/src/mesa/state_tracker/st_draw_feedback.c
> +++ b/src/mesa/state_tracker/st_draw_feedback.c
> @@ -95,7 +95,8 @@ st_feedback_draw_vbo(struct gl_context *ctx,
> GLboolean index_bounds_valid,
> GLuint min_index,
> GLuint max_index,
> - struct gl_transform_feedback_object *tfb_vertcount)
> + struct gl_transform_feedback_object *tfb_vertcount,
> + struct gl_buffer_object *indirect)
> {
> struct st_context *st = st_context(ctx);
> struct pipe_context *pipe = st->pipe;
> diff --git a/src/mesa/tnl/tnl.h b/src/mesa/tnl/tnl.h
> index 9583228..ad361ea 100644
> --- a/src/mesa/tnl/tnl.h
> +++ b/src/mesa/tnl/tnl.h
> @@ -92,7 +92,8 @@ _tnl_vbo_draw_prims( struct gl_context *ctx,
> GLboolean index_bounds_valid,
> GLuint min_index,
> GLuint max_index,
> - struct gl_transform_feedback_object *tfb_vertcount );
> + struct gl_transform_feedback_object *tfb_vertcount,
> + struct gl_buffer_object *indirect );
const-qualify indirect?
>
> extern void
> _tnl_RasterPos(struct gl_context *ctx, const GLfloat vObj[4]);
> diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h
> index 49dab23..7156c35 100644
> --- a/src/mesa/vbo/vbo.h
> +++ b/src/mesa/vbo/vbo.h
> @@ -52,6 +52,8 @@ struct _mesa_prim {
> GLint basevertex;
> GLuint num_instances;
> GLuint base_instance;
> +
> + GLsizeiptr indirect_offset;
> };
>
> /* Would like to call this a "vbo_index_buffer", but this would be
> @@ -79,7 +81,8 @@ typedef void (*vbo_draw_func)( struct gl_context *ctx,
> GLboolean index_bounds_valid,
> GLuint min_index,
> GLuint max_index,
> - struct gl_transform_feedback_object *tfb_vertcount );
> + struct gl_transform_feedback_object *tfb_vertcount,
> + struct gl_buffer_object *indirect );
const-qualify here too?
>
>
>
> diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c
> index 7e61f7b..cd6ca2c 100644
> --- a/src/mesa/vbo/vbo_exec_array.c
> +++ b/src/mesa/vbo/vbo_exec_array.c
> @@ -542,7 +542,7 @@ vbo_handle_primitive_restart(struct gl_context *ctx,
> } else {
> /* Call driver directly for draw_prims */
> vbo->draw_prims(ctx, prim, nr_prims, ib,
> - index_bounds_valid, min_index, max_index, NULL);
> + index_bounds_valid, min_index, max_index, NULL, NULL);
> }
> }
>
> @@ -607,7 +607,7 @@ vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
> /* draw one or two prims */
> check_buffers_are_unmapped(exec->array.inputs);
> vbo->draw_prims(ctx, prim, primCount, NULL,
> - GL_TRUE, start, start + count - 1, NULL);
> + GL_TRUE, start, start + count - 1, NULL, NULL);
> }
> }
> else {
> @@ -618,7 +618,7 @@ vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
> check_buffers_are_unmapped(exec->array.inputs);
> vbo->draw_prims(ctx, prim, 1, NULL,
> GL_TRUE, start, start + count - 1,
> - NULL);
> + NULL, NULL);
> }
>
> if (MESA_DEBUG_FLAGS& DEBUG_ALWAYS_FLUSH) {
> @@ -1285,7 +1285,7 @@ vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
>
> check_buffers_are_unmapped(exec->array.inputs);
> vbo->draw_prims(ctx, prim, 1, NULL,
> - GL_TRUE, 0, 0, obj);
> + GL_TRUE, 0, 0, obj, NULL);
>
> if (MESA_DEBUG_FLAGS& DEBUG_ALWAYS_FLUSH) {
> _mesa_flush(ctx);
> @@ -1359,6 +1359,249 @@ vbo_exec_DrawTransformFeedbackStreamInstanced(GLenum mode, GLuint name,
> vbo_draw_transform_feedback(ctx, mode, obj, stream, primcount);
> }
>
> +static void
> +vbo_validated_drawarraysindirect(struct gl_context *ctx,
> + GLenum mode, const GLvoid *indirect)
> +{
> + struct vbo_context *vbo = vbo_context(ctx);
> + struct vbo_exec_context *exec =&vbo->exec;
> + struct _mesa_prim prim[1];
> +
> + vbo_bind_arrays(ctx);
> +
> + memset(prim, 0, sizeof(prim));
> + prim[0].begin = 1;
> + prim[0].end = 1;
> + prim[0].mode = mode;
> + prim[0].indirect_offset = (GLsizeiptr)indirect;
> +
> + /* NOTE: We do NOT want to handle primitive restart here, nor perform any
> + * other checks that require knowledge of the values in the command buffer.
> + * That would deafeat the whole purpose of this function.
> + */
> +
> + check_buffers_are_unmapped(exec->array.inputs);
> + vbo->draw_prims(ctx, prim, 1,
> + NULL, GL_TRUE, 0, 0,
> + NULL,
> + ctx->DrawIndirectBuffer);
> +
> + if (MESA_DEBUG_FLAGS& DEBUG_ALWAYS_FLUSH)
> + _mesa_flush(ctx);
> +}
> +
> +static void
> +vbo_validated_multidrawarraysindirect(struct gl_context *ctx,
> + GLenum mode,
> + const GLvoid *indirect,
> + GLsizei primcount, GLsizei stride)
> +{
> + struct vbo_context *vbo = vbo_context(ctx);
> + struct vbo_exec_context *exec =&vbo->exec;
> + struct _mesa_prim *prim;
> + GLsizei i;
> + GLsizeiptr offset = (GLsizeiptr)indirect;
> +
> + if (primcount == 0)
> + return;
> + prim = calloc(1, primcount * sizeof(*prim));
> + if (prim == NULL) {
> + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawArraysIndirect");
> + return;
> + }
> +
> + vbo_bind_arrays(ctx);
> +
> + memset(prim, 0, primcount * sizeof(*prim));
> + prim[0].begin = 1;
> + prim[primcount - 1].end = 1;
> + for (i = 0; i< primcount; ++i, offset += stride) {
> + prim[i].mode = mode;
> + prim[i].indirect_offset = offset;
> + }
> +
> + check_buffers_are_unmapped(exec->array.inputs);
> + vbo->draw_prims(ctx, prim, primcount,
> + NULL, GL_TRUE, 0, 0,
> + NULL,
> + ctx->DrawIndirectBuffer);
> +
> + free(prim);
> +
> + if (MESA_DEBUG_FLAGS& DEBUG_ALWAYS_FLUSH)
> + _mesa_flush(ctx);
> +}
> +
> +static void
> +vbo_validated_drawelementsindirect(struct gl_context *ctx,
> + GLenum mode, GLenum type,
> + const GLvoid *indirect)
> +{
> + struct vbo_context *vbo = vbo_context(ctx);
> + struct vbo_exec_context *exec =&vbo->exec;
> + struct _mesa_index_buffer ib;
> + struct _mesa_prim prim[1];
> +
> + vbo_bind_arrays(ctx);
> +
> + ib.count = 0; /* unknown */
> + ib.type = type;
> + ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
> + ib.ptr = NULL;
> +
> + memset(prim, 0, sizeof(prim));
> + prim[0].begin = 1;
> + prim[0].end = 1;
> + prim[0].mode = mode;
> + prim[0].indexed = 1;
> + prim[0].indirect_offset = (GLsizeiptr)indirect;
> +
> + check_buffers_are_unmapped(exec->array.inputs);
> + vbo->draw_prims(ctx, prim, 1,
> +&ib, GL_TRUE, 0, 0,
> + NULL,
> + ctx->DrawIndirectBuffer);
> +
> + if (MESA_DEBUG_FLAGS& DEBUG_ALWAYS_FLUSH)
> + _mesa_flush(ctx);
> +}
> +
> +static void
> +vbo_validated_multidrawelementsindirect(struct gl_context *ctx,
> + GLenum mode, GLenum type,
> + const GLvoid *indirect,
> + GLsizei primcount, GLsizei stride)
> +{
> + struct vbo_context *vbo = vbo_context(ctx);
> + struct vbo_exec_context *exec =&vbo->exec;
> + struct _mesa_index_buffer ib;
> + struct _mesa_prim *prim;
> + GLsizei i;
> + GLsizeiptr offset = (GLsizeiptr)indirect;
> +
> + if (primcount == 0)
> + return;
> + prim = calloc(1, primcount * sizeof(*prim));
> + if (prim == NULL) {
> + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElementsIndirect");
> + return;
> + }
> +
> + vbo_bind_arrays(ctx);
> +
> + /* NOTE: ElementArrayBufferObj is guaranteed to be a VBO. */
> +
> + ib.count = 0; /* unknown */
> + ib.type = type;
> + ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
> + ib.ptr = NULL;
> +
> + memset(prim, 0, primcount * sizeof(*prim));
> + prim[0].begin = 1;
> + prim[primcount - 1].end = 1;
> + for (i = 0; i< primcount; ++i, offset += stride) {
> + prim[i].mode = mode;
> + prim[i].indexed = 1;
> + prim[i].indirect_offset = offset;
> + }
> +
> + check_buffers_are_unmapped(exec->array.inputs);
> + vbo->draw_prims(ctx, prim, primcount,
> +&ib, GL_TRUE, 0, 0,
> + NULL,
> + ctx->DrawIndirectBuffer);
> +
> + free(prim);
> +
> + if (MESA_DEBUG_FLAGS& DEBUG_ALWAYS_FLUSH)
> + _mesa_flush(ctx);
> +}
> +
> +/**
> + * Like [Multi]DrawArrays/Elements, but they take most arguments from
> + * a buffer object.
> + */
> +static void GLAPIENTRY
> +vbo_exec_DrawArraysIndirect(GLenum mode, const GLvoid *indirect)
> +{
> + GET_CURRENT_CONTEXT(ctx);
> +
> + if (MESA_VERBOSE& VERBOSE_DRAW)
> + _mesa_debug(ctx, "glDrawArraysIndirect(%s, %p)\n",
> + _mesa_lookup_enum_by_nr(mode), indirect);
> +
> + if (!_mesa_validate_DrawArraysIndirect(ctx, mode, indirect))
> + return;
> +
> + vbo_validated_drawarraysindirect(ctx, mode, indirect);
> +}
> +
> +static void GLAPIENTRY
> +vbo_exec_DrawElementsIndirect(GLenum mode, GLenum type,
> + const GLvoid *indirect)
> +{
> + GET_CURRENT_CONTEXT(ctx);
> +
> + if (MESA_VERBOSE& VERBOSE_DRAW)
> + _mesa_debug(ctx, "glDrawElementsIndirect(%s, %s, %p)\n",
> + _mesa_lookup_enum_by_nr(mode),
> + _mesa_lookup_enum_by_nr(type), indirect);
> +
> + if (!_mesa_validate_DrawElementsIndirect(ctx, mode, type, indirect))
> + return;
> +
> + vbo_validated_drawelementsindirect(ctx, mode, type, indirect);
> +}
> +
> +static void GLAPIENTRY
> +vbo_exec_MultiDrawArraysIndirect(GLenum mode,
> + const GLvoid *indirect,
> + GLsizei primcount, GLsizei stride)
> +{
> + GET_CURRENT_CONTEXT(ctx);
> +
> + if (MESA_VERBOSE& VERBOSE_DRAW)
> + _mesa_debug(ctx, "glMultiDrawArraysIndirect(%s, %p, %i, %i)\n",
> + _mesa_lookup_enum_by_nr(mode), indirect, primcount, stride);
> +
> + if (stride == 0)
> + stride = 4 * sizeof(GLuint);
Maybe document where the '4' comes from (the spec's
DrawArraysIndirectCommand struct). And 5 below.
> +
> + if (!_mesa_validate_MultiDrawArraysIndirect(ctx, mode,
> + indirect,
> + primcount, stride))
> + return;
> +
> + vbo_validated_multidrawarraysindirect(ctx, mode,
> + indirect,
> + primcount, stride);
> +}
> +
> +static void GLAPIENTRY
> +vbo_exec_MultiDrawElementsIndirect(GLenum mode, GLenum type,
> + const GLvoid *indirect,
> + GLsizei primcount, GLsizei stride)
> +{
> + GET_CURRENT_CONTEXT(ctx);
> +
> + if (MESA_VERBOSE& VERBOSE_DRAW)
> + _mesa_debug(ctx, "glMultiDrawElementsIndirect(%s, %s, %p, %i, %i)\n",
> + _mesa_lookup_enum_by_nr(mode),
> + _mesa_lookup_enum_by_nr(type), indirect, primcount, stride);
> +
> + if (stride == 0)
> + stride = 5 * sizeof(GLuint);
> +
> + if (!_mesa_validate_MultiDrawElementsIndirect(ctx, mode, type,
> + indirect,
> + primcount, stride))
> + return;
> +
> + vbo_validated_multidrawelementsindirect(ctx, mode, type,
> + indirect,
> + primcount, stride);
> +}
> +
> /**
> * Plug in the immediate-mode vertex array drawing commands into the
> * givven vbo_exec_context object.
> @@ -1386,6 +1629,10 @@ vbo_exec_array_init( struct vbo_exec_context *exec )
> vbo_exec_DrawTransformFeedbackInstanced;
> exec->vtxfmt.DrawTransformFeedbackStreamInstanced =
> vbo_exec_DrawTransformFeedbackStreamInstanced;
> + exec->vtxfmt.DrawArraysIndirect = vbo_exec_DrawArraysIndirect;
> + exec->vtxfmt.DrawElementsIndirect = vbo_exec_DrawElementsIndirect;
> + exec->vtxfmt.MultiDrawArraysIndirect = vbo_exec_MultiDrawArraysIndirect;
> + exec->vtxfmt.MultiDrawElementsIndirect = vbo_exec_MultiDrawElementsIndirect;
> }
>
>
> diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c
> index 9529ce0..1122356 100644
> --- a/src/mesa/vbo/vbo_exec_draw.c
> +++ b/src/mesa/vbo/vbo_exec_draw.c
> @@ -404,7 +404,7 @@ vbo_exec_vtx_flush(struct vbo_exec_context *exec, GLboolean keepUnmapped)
> GL_TRUE,
> 0,
> exec->vtx.vert_count - 1,
> - NULL);
> + NULL, NULL);
>
> /* If using a real VBO, get new storage -- unless asked not to.
> */
> diff --git a/src/mesa/vbo/vbo_primitive_restart.c b/src/mesa/vbo/vbo_primitive_restart.c
> index a6a0149..38b4766 100644
> --- a/src/mesa/vbo/vbo_primitive_restart.c
> +++ b/src/mesa/vbo/vbo_primitive_restart.c
> @@ -213,11 +213,11 @@ vbo_sw_primitive_restart(struct gl_context *ctx,
> (temp_prim.count == sub_prim->count)) {
> draw_prims_func(ctx,&temp_prim, 1, ib,
> GL_TRUE, sub_prim->min_index, sub_prim->max_index,
> - NULL);
> + NULL, NULL);
> } else {
> draw_prims_func(ctx,&temp_prim, 1, ib,
> GL_FALSE, -1, -1,
> - NULL);
> + NULL, NULL);
> }
> }
> if (sub_end_index>= end_index) {
> diff --git a/src/mesa/vbo/vbo_rebase.c b/src/mesa/vbo/vbo_rebase.c
> index d0bf6c5..828e667 100644
> --- a/src/mesa/vbo/vbo_rebase.c
> +++ b/src/mesa/vbo/vbo_rebase.c
> @@ -237,7 +237,7 @@ void vbo_rebase_prims( struct gl_context *ctx,
> GL_TRUE,
> 0,
> max_index - min_index,
> - NULL );
> + NULL, NULL );
>
> ctx->Array._DrawArrays = saved_arrays;
> ctx->NewDriverState |= ctx->DriverFlags.NewArray;
> diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c
> index 7490717..37e3342 100644
> --- a/src/mesa/vbo/vbo_save_api.c
> +++ b/src/mesa/vbo/vbo_save_api.c
> @@ -1151,6 +1151,55 @@ _save_DrawTransformFeedbackStreamInstanced(GLenum mode, GLuint name,
>
>
> static void GLAPIENTRY
> +_save_DrawArraysIndirect(GLenum mode, const GLvoid *indirect)
> +{
> + GET_CURRENT_CONTEXT(ctx);
> + (void) mode;
> + (void) indirect;
> + _mesa_compile_error(ctx, GL_INVALID_OPERATION, "glDrawArraysIndirect");
> +}
> +
> +
> +static void GLAPIENTRY
> +_save_DrawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect)
> +{
> + GET_CURRENT_CONTEXT(ctx);
> + (void) mode;
> + (void) type;
> + (void) indirect;
> + _mesa_compile_error(ctx, GL_INVALID_OPERATION, "glDrawElementsIndirect");
> +}
> +
> +
> +static void GLAPIENTRY
> +_save_MultiDrawArraysIndirect(GLenum mode, const GLvoid *indirect,
> + GLsizei primcount, GLsizei stride)
> +{
> + GET_CURRENT_CONTEXT(ctx);
> + (void) mode;
> + (void) indirect;
> + (void) primcount;
> + (void) stride;
> + _mesa_compile_error(ctx, GL_INVALID_OPERATION, "glMultiDrawArraysIndirect");
> +}
> +
> +
> +static void GLAPIENTRY
> +_save_MultiDrawElementsIndirect(GLenum mode, GLenum type,
> + const GLvoid *indirect,
> + GLsizei primcount, GLsizei stride)
> +{
> + GET_CURRENT_CONTEXT(ctx);
> + (void) mode;
> + (void) type;
> + (void) indirect;
> + (void) primcount;
> + (void) stride;
> + _mesa_compile_error(ctx, GL_INVALID_OPERATION, "glMultiDrawElementsIndirect");
> +}
> +
> +
> +static void GLAPIENTRY
> _save_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
> {
> GET_CURRENT_CONTEXT(ctx);
> @@ -1506,6 +1555,10 @@ _save_vtxfmt_init(struct gl_context *ctx)
> vfmt->DrawTransformFeedbackInstanced = _save_DrawTransformFeedbackInstanced;
> vfmt->DrawTransformFeedbackStreamInstanced =
> _save_DrawTransformFeedbackStreamInstanced;
> + vfmt->DrawArraysIndirect = _save_DrawArraysIndirect;
> + vfmt->DrawElementsIndirect = _save_DrawElementsIndirect;
> + vfmt->MultiDrawArraysIndirect = _save_MultiDrawArraysIndirect;
> + vfmt->MultiDrawElementsIndirect = _save_MultiDrawElementsIndirect;
> }
>
>
> diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c
> index f5b5c41..84ff3f7 100644
> --- a/src/mesa/vbo/vbo_save_draw.c
> +++ b/src/mesa/vbo/vbo_save_draw.c
> @@ -319,7 +319,7 @@ vbo_save_playback_vertex_list(struct gl_context *ctx, void *data)
> GL_TRUE,
> 0, /* Node is a VBO, so this is ok */
> node->count - 1,
> - NULL);
> + NULL, NULL);
> }
> }
>
> diff --git a/src/mesa/vbo/vbo_split_copy.c b/src/mesa/vbo/vbo_split_copy.c
> index a917f39..51c4a3a 100644
> --- a/src/mesa/vbo/vbo_split_copy.c
> +++ b/src/mesa/vbo/vbo_split_copy.c
> @@ -201,7 +201,7 @@ flush( struct copy_context *copy )
> GL_TRUE,
> 0,
> copy->dstbuf_nr - 1,
> - NULL );
> + NULL, NULL );
>
> ctx->Array._DrawArrays = saved_arrays;
> ctx->NewDriverState |= ctx->DriverFlags.NewArray;
> diff --git a/src/mesa/vbo/vbo_split_inplace.c b/src/mesa/vbo/vbo_split_inplace.c
> index 8a38308..a9ae8f1 100644
> --- a/src/mesa/vbo/vbo_split_inplace.c
> +++ b/src/mesa/vbo/vbo_split_inplace.c
> @@ -94,7 +94,7 @@ static void flush_vertex( struct split_context *split )
> !split->ib,
> split->min_index,
> split->max_index,
> - NULL);
> + NULL, NULL);
>
> ctx->Array._DrawArrays = saved_arrays;
> ctx->NewDriverState |= ctx->DriverFlags.NewArray;
More information about the mesa-dev
mailing list