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;

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to