<div dir="ltr">On 4 November 2013 06:57, Brian Paul <span dir="ltr"><<a href="mailto:brianp@vmware.com" target="_blank">brianp@vmware.com</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

<div><div>On 11/04/2013 02:09 AM, Chris Forbes wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
From: Christoph Bumiller <<a href="mailto:e0425955@student.tuwien.ac.at" target="_blank">e0425955@student.tuwien.ac.at</a><u></u>><br>
<br>
</blockquote></div></div><div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
diff --git a/src/mapi/glapi/gen/ARB_draw_<u></u>indirect.xml b/src/mapi/glapi/gen/ARB_draw_<u></u>indirect.xml<br>
new file mode 100644<br>
index 0000000..7de03cd<br>
--- /dev/null<br>
+++ b/src/mapi/glapi/gen/ARB_draw_<u></u>indirect.xml<br>
@@ -0,0 +1,45 @@<br>
+<?xml version="1.0"?><br>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd"><br>
+<br>
+<OpenGLAPI><br>
+<br>
+<category name="GL_ARB_draw_indirect" number="87"><br>
+<br>
+    <enum name="DRAW_INDIRECT_BUFFER"                   value="0x8F3F"/><br>
+    <enum name="DRAW_INDIRECT_BUFFER_<u></u>BINDING"           value="0x8F43"/><br>
+<br>
+    <function name="DrawArraysIndirect" offset="assign" exec="dynamic"><br>
+        <param name="mode" type="GLenum"/><br>
+        <param name="indirect" type="const GLvoid *"/><br>
</blockquote>
<br></div>
The use of GLvoid has been removed in glext.h and I'd be OK with doing the same in the dispatch code.</blockquote><div><br></div><div>I'd be in favor of that too, but I think it should be done as a separate patch series--at the moment all the dispatch xml consistently uses GLvoid, so IMHO we should stay consistent for now, and then later switch everything over to "void" in one fell swoop.<br>

</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div><br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+    </function><br>
+<br>
+    <function name="DrawElementsIndirect" offset="assign" exec="dynamic"><br>
+        <param name="mode" type="GLenum"/><br>
+        <param name="type" type="GLenum"/><br>
+        <param name="indirect" type="const GLvoid *"/><br>
+    </function><br>
+<br>
+</category><br>
+<br>
+<br>
+<category name="GL_ARB_multi_draw_<u></u>indirect" number="133"><br>
+<br>
+    <function name="MultiDrawArraysIndirect" offset="assign" exec="dynamic"><br>
+        <param name="mode" type="GLenum"/><br>
+        <param name="indirect" type="const GLvoid *"/><br>
+        <param name="primcount" type="GLsizei"/><br>
+        <param name="stride" type="GLsizei"/><br>
+    </function><br>
+<br>
+    <function name="<u></u>MultiDrawElementsIndirect" offset="assign" exec="dynamic"><br>
+        <param name="mode" type="GLenum"/><br>
+        <param name="type" type="GLenum"/><br>
+        <param name="indirect" type="const GLvoid *"/><br>
+        <param name="primcount" type="GLsizei"/><br>
+        <param name="stride" type="GLsizei"/><br>
+    </function><br>
+<br>
+</category><br>
+<br>
+<br>
+</OpenGLAPI><br>
diff --git a/src/mapi/glapi/gen/Makefile.<u></u>am b/src/mapi/glapi/gen/Makefile.<u></u>am<br>
index cbbf659..0c67513 100644<br>
--- a/src/mapi/glapi/gen/Makefile.<u></u>am<br>
+++ b/src/mapi/glapi/gen/Makefile.<u></u>am<br>
@@ -98,6 +98,7 @@ API_XML = \<br>
        ARB_draw_buffers.xml \<br>
        ARB_draw_buffers_blend.xml \<br>
        ARB_draw_elements_base_vertex.<u></u>xml \<br>
+       ARB_draw_indirect.xml \<br>
        ARB_draw_instanced.xml \<br>
        ARB_ES2_compatibility.xml \<br>
        ARB_ES3_compatibility.xml \<br>
diff --git a/src/mapi/glapi/gen/gl_API.<u></u>xml b/src/mapi/glapi/gen/gl_API.<u></u>xml<br>
index 69014c5..7cab5ba 100644<br>
--- a/src/mapi/glapi/gen/gl_API.<u></u>xml<br>
+++ b/src/mapi/glapi/gen/gl_API.<u></u>xml<br>
@@ -8241,6 +8241,8 @@<br>
<br>
  <!-- ARB extensions #86...#93 --><br>
<br>
+<xi:include href="ARB_draw_indirect.xml" xmlns:xi="<a href="http://www.w3.org/2001/XInclude" target="_blank">http://www.w3.org/<u></u>2001/XInclude</a>"/><br>
+<br>
  <category name="GL_ARB_transform_<u></u>feedback3" number="94"><br>
    <enum name="MAX_TRANSFORM_FEEDBACK_<u></u>BUFFERS" value="0x8E70"/><br>
    <enum name="MAX_VERTEX_STREAMS"             value="0x8E71"/><br>
@@ -8466,7 +8468,7 @@<br>
<br>
  <xi:include href="ARB_invalidate_subdata.<u></u>xml" xmlns:xi="<a href="http://www.w3.org/2001/XInclude" target="_blank">http://www.w3.org/<u></u>2001/XInclude</a>"/><br>
<br>
-<!-- ARB extensions #133...#138 --><br>
+<!-- ARB extensions #134...#138 --><br>
<br>
  <xi:include href="ARB_texture_buffer_<u></u>range.xml" xmlns:xi="<a href="http://www.w3.org/2001/XInclude" target="_blank">http://www.w3.org/<u></u>2001/XInclude</a>"/><br>
<br>
diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c<br>
index f285c97..f3128cb 100644<br>
--- a/src/mesa/main/api_validate.c<br>
+++ b/src/mesa/main/api_validate.c<br>
@@ -837,3 +837,156 @@ _mesa_validate_<u></u>DrawTransformFeedback(struct gl_context *ctx,<br>
<br>
     return GL_TRUE;<br>
  }<br>
+<br>
</blockquote>
<br></div></div>
Maybe put a comment on this describing what 'size' is.<div><div><br>
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+static GLboolean<br>
+valid_draw_indirect(struct gl_context *ctx,<br>
+                    GLenum mode, const GLvoid *indirect,<br>
+                    GLsizei size, const char *name)<br>
+{<br>
+   const GLsizeiptr end = (GLsizeiptr)indirect + size;<br>
+<br>
+   if (!_mesa_valid_prim_mode(ctx, mode, name))<br>
+      return GL_FALSE;<br>
+<br>
+   if ((GLsizeiptr)indirect & (sizeof(GLuint) - 1)) {<br>
+      _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+                  "%s(indirect is not aligned)", name);<br>
+      return GL_FALSE;<br>
+   }<br>
+<br>
+   if (_mesa_is_bufferobj(ctx-><u></u>DrawIndirectBuffer)) {<br>
+      if (_mesa_bufferobj_mapped(ctx-><u></u>DrawIndirectBuffer)) {<br>
+         _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+                     "%s(DRAW_INDIRECT_BUFFER is mapped)", name);<br>
+         return GL_FALSE;<br>
+      }<br>
+      if (ctx->DrawIndirectBuffer->Size < end) {<br>
+         _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+                     "%s(DRAW_INDIRECT_BUFFER too small)", name);<br>
+         return GL_FALSE;<br>
+      }<br>
+   } else {<br>
+      if (ctx->API != API_OPENGL_COMPAT) {<br>
+         _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+                     "%s: no buffer bound to DRAW_INDIRECT_BUFFER", name);<br>
+         return GL_FALSE;<br>
+      }<br>
+   }<br>
+<br>
+   if (!check_valid_to_render(ctx, name))<br>
+      return GL_FALSE;<br>
+<br>
+   return GL_TRUE;<br>
+}<br>
+<br>
+static inline GLboolean<br>
+valid_draw_indirect_elements(<u></u>struct gl_context *ctx,<br>
+                             GLenum mode, GLenum type, const GLvoid *indirect,<br>
+                             GLsizeiptr size, const char *name)<br>
+{<br>
+   if (!valid_elements_type(ctx, type, name))<br>
+      return GL_FALSE;<br>
+<br>
+   /*<br>
+    * Unlike regular DrawElementsInstancedBaseVerte<u></u>x commands, the indices<br>
+    * may not come from a client array and must come from an index buffer.<br>
+    * If no element array buffer is bound, an INVALID_OPERATION error is<br>
+    * generated.<br>
+    */<br>
+   if (!_mesa_is_bufferobj(ctx-><u></u>Array.ArrayObj-><u></u>ElementArrayBufferObj)) {<br>
+      _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+                  "%s(no buffer bound to GL_ELEMENT_ARRAY_BUFFER)", name);<br>
+      return GL_FALSE;<br>
+   }<br>
+<br>
+   return valid_draw_indirect(ctx, mode, indirect, size, name);<br>
+}<br>
+<br>
+static inline GLboolean<br>
+valid_draw_indirect_multi(<u></u>struct gl_context *ctx,<br>
+                          GLsizei primcount, GLsizei stride,<br>
+                          const char *name)<br>
+{<br>
+   if (primcount < 0) {<br>
+      _mesa_error(ctx, GL_INVALID_VALUE, "%s(primcount < 0)", name);<br>
+      return GL_FALSE;<br>
+   }<br>
+<br>
+   if (stride % 4) {<br>
+      _mesa_error(ctx, GL_INVALID_VALUE, "%s(stride %% 4)", name);<br>
+      return GL_FALSE;<br>
+   }<br>
+<br>
+   return GL_TRUE;<br>
+}<br>
+<br>
+GLboolean<br>
+_mesa_validate_<u></u>DrawArraysIndirect(struct gl_context *ctx,<br>
+                                  GLenum mode,<br>
+                                  const GLvoid *indirect)<br>
+{<br>
+   FLUSH_CURRENT(ctx, 0);<br>
+<br>
+   return valid_draw_indirect(ctx, mode,<br>
+                              indirect, 4 * sizeof(GLuint),<br>
</blockquote>
<br></div></div>
4 here and 5 below, etc. seem like magic numbers.  How about declaring and using a local var such as "const unsigned drawArraysNumParams = 4;" to clarify?<div><br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+                              "glDrawArraysIndirect");<br>
+}<br>
+<br>
+GLboolean<br>
+_mesa_validate_<u></u>DrawElementsIndirect(struct gl_context *ctx,<br>
+                                    GLenum mode, GLenum type,<br>
+                                    const GLvoid *indirect)<br>
+{<br>
+   FLUSH_CURRENT(ctx, 0);<br>
+<br>
+   return valid_draw_indirect_elements(<u></u>ctx, mode, type,<br>
+                                       indirect, 5 * sizeof(GLuint),<br>
+                                       "glDrawElementsIndirect");<br>
+}<br>
+<br>
+GLboolean<br>
+_mesa_validate_<u></u>MultiDrawArraysIndirect(struct gl_context *ctx,<br>
+                                       GLenum mode,<br>
+                                       const GLvoid *indirect,<br>
+                                       GLsizei primcount, GLsizei stride)<br>
+{<br>
+   GLsizeiptr size = 0;<br>
+   if (primcount) /* &(last command) + sizeof(<u></u>DrawArraysIndirectCommand) */<br>
</blockquote>
<br></div>
Is the commented code a debug left-over?<div><br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+      size = (primcount - 1) * stride + 4 * sizeof(GLuint);<br>
+<br>
+   FLUSH_CURRENT(ctx, 0);<br>
+<br>
+   if (!valid_draw_indirect_multi(<u></u>ctx, primcount, stride,<br>
+                                  "glMultiDrawArraysIndirect"))<br>
+      return GL_FALSE;<br>
+<br>
+   if (!valid_draw_indirect(ctx, mode, indirect, size,<br>
+                            "glMultiDrawArraysIndirect"))<br>
+      return GL_FALSE;<br>
+<br>
+   return GL_TRUE;<br>
+}<br>
+<br>
+GLboolean<br>
+_mesa_validate_<u></u>MultiDrawElementsIndirect(<u></u>struct gl_context *ctx,<br>
+                                         GLenum mode, GLenum type,<br>
+                                         const GLvoid *indirect,<br>
+                                         GLsizei primcount, GLsizei stride)<br>
+{<br>
+   GLsizeiptr size = 0;<br>
</blockquote>
<br></div>
Insert blank line here.<div><div><br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+   if (primcount) /* &(last command) + sizeof(<u></u>DrawElementsIndirectCommand) */<br>
+      size = (primcount - 1) * stride + 5 * sizeof(GLuint);<br>
+<br>
+   FLUSH_CURRENT(ctx, 0);<br>
+<br>
+   if (!valid_draw_indirect_multi(<u></u>ctx, primcount, stride,<br>
+                                  "glMultiDrawElementsIndirect")<u></u>)<br>
+      return GL_FALSE;<br>
+<br>
+   if (!valid_draw_indirect_<u></u>elements(ctx, mode, type,<br>
+                                     indirect, size,<br>
+                                     "glMultiDrawElementsIndirect")<u></u>)<br>
+      return GL_FALSE;<br>
+<br>
+   return GL_TRUE;<br>
+}<br>
diff --git a/src/mesa/main/api_validate.h b/src/mesa/main/api_validate.h<br>
index f2b753c..8238df1 100644<br>
--- a/src/mesa/main/api_validate.h<br>
+++ b/src/mesa/main/api_validate.h<br>
@@ -87,5 +87,31 @@ _mesa_validate_<u></u>DrawTransformFeedback(struct gl_context *ctx,<br>
                                       GLuint stream,<br>
                                       GLsizei numInstances);<br>
<br>
+extern GLboolean<br>
+_mesa_validate_<u></u>DrawArraysIndirect(struct gl_context *ctx,<br>
+                                  GLenum mode,<br>
+                                  const GLvoid *indirect);<br>
+<br>
+extern GLboolean<br>
+_mesa_validate_<u></u>DrawElementsIndirect(struct gl_context *ctx,<br>
+                                    GLenum mode,<br>
+                                    GLenum type,<br>
+                                    const GLvoid *indirect);<br>
+<br>
+extern GLboolean<br>
+_mesa_validate_<u></u>MultiDrawArraysIndirect(struct gl_context *ctx,<br>
+                                       GLenum mode,<br>
+                                       const GLvoid *indirect,<br>
+                                       GLsizei primcount,<br>
+                                       GLsizei stride);<br>
+<br>
+extern GLboolean<br>
+_mesa_validate_<u></u>MultiDrawElementsIndirect(<u></u>struct gl_context *ctx,<br>
+                                         GLenum mode,<br>
+                                         GLenum type,<br>
+                                         const GLvoid *indirect,<br>
+                                         GLsizei primcount,<br>
+                                         GLsizei stride);<br>
+<br>
<br>
  #endif<br>
diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c<br>
index 1f55061..69ea1c0 100644<br>
--- a/src/mesa/main/bufferobj.c<br>
+++ b/src/mesa/main/bufferobj.c<br>
@@ -86,6 +86,10 @@ get_buffer_target(struct gl_context *ctx, GLenum target)<br>
        return &ctx->CopyReadBuffer;<br>
     case GL_COPY_WRITE_BUFFER:<br>
        return &ctx->CopyWriteBuffer;<br>
+   case GL_DRAW_INDIRECT_BUFFER:<br>
+      if (ctx->Extensions.ARB_draw_<u></u>indirect)<br>
+         return &ctx->DrawIndirectBuffer;<br>
+      break;<br>
     case GL_TRANSFORM_FEEDBACK_BUFFER:<br>
        if (ctx->Extensions.EXT_<u></u>transform_feedback) {<br>
           return &ctx->TransformFeedback.<u></u>CurrentBuffer;<br>
@@ -626,6 +630,9 @@ _mesa_init_buffer_objects( struct gl_context *ctx )<br>
     _mesa_reference_buffer_object(<u></u>ctx, &ctx->UniformBuffer,<br>
                                 ctx->Shared->NullBufferObj);<br>
<br>
+   _mesa_reference_buffer_object(<u></u>ctx, &ctx->DrawIndirectBuffer,<br>
+                                ctx->Shared->NullBufferObj);<br>
+<br>
     for (i = 0; i < MAX_COMBINED_UNIFORM_BUFFERS; i++) {<br>
        _mesa_reference_buffer_object(<u></u>ctx,<br>
                                    &ctx->UniformBufferBindings[i]<u></u>.BufferObject,<br>
@@ -873,6 +880,11 @@ _mesa_DeleteBuffers(GLsizei n, const GLuint *ids)<br>
              _mesa_BindBuffer( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 );<br>
           }<br>
<br>
+         /* unbind ARB_draw_indirect binding point */<br>
+         if (ctx->DrawIndirectBuffer == bufObj) {<br>
+            _mesa_BindBuffer( GL_DRAW_INDIRECT_BUFFER, 0 );<br>
+         }<br>
+<br>
           /* unbind ARB_copy_buffer binding points */<br>
           if (ctx->CopyReadBuffer == bufObj) {<br>
              _mesa_BindBuffer( GL_COPY_READ_BUFFER, 0 );<br>
diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c<br>
index 5956419..c953ffb 100644<br>
--- a/src/mesa/main/dlist.c<br>
+++ b/src/mesa/main/dlist.c<br>
@@ -1356,6 +1356,42 @@ save_<u></u>DrawElementsInstancedBaseVerte<u></u>xBaseInstance(GLenum mode,<br>
               "<u></u>glDrawElementsInstancedBaseVer<u></u>texBaseInstance() during display list compile");<br>
  }<br>
<br>
+/* GL_ARB_draw_indirect. */<br>
+static void GLAPIENTRY<br>
+save_DrawArraysIndirect(<u></u>GLenum mode, const GLvoid *indirect)<br>
+{<br>
+   GET_CURRENT_CONTEXT(ctx);<br>
+   _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+              "glDrawArraysIndirect() during display list compile");<br>
+}<br>
+<br>
+static void GLAPIENTRY<br>
+save_DrawElementsIndirect(<u></u>GLenum mode, GLenum type, const GLvoid *indirect)<br>
+{<br>
+   GET_CURRENT_CONTEXT(ctx);<br>
+   _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+              "glDrawElementsIndirect() during display list compile");<br>
+}<br>
+<br>
+/* GL_ARB_multi_draw_indirect. */<br>
+static void GLAPIENTRY<br>
+save_MultiDrawArraysIndirect(<u></u>GLenum mode, const GLvoid *indirect,<br>
+                             GLsizei primcount, GLsizei stride)<br>
+{<br>
+   GET_CURRENT_CONTEXT(ctx);<br>
+   _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+              "glMultiDrawArraysIndirect() during display list compile");<br>
+}<br>
+<br>
+static void GLAPIENTRY<br>
+save_<u></u>MultiDrawElementsIndirect(<u></u>GLenum mode, GLenum type,<br>
+                               const GLvoid *indirect,<br>
+                               GLsizei primcount, GLsizei stride)<br>
+{<br>
+   GET_CURRENT_CONTEXT(ctx);<br>
+   _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+              "glMultiDrawElementsIndirect() during display list compile");<br>
+}<br>
</blockquote>
<br></div></div>
I thought that when we build/init the display list 'save' dispatch table, the unused entries point to a generic function that generates GL_INVALID_OPERATION.  In that case, I don't think we'd need these functions.  I'd have to dig into the code to be sure though.</blockquote>

<div><br></div><div>I don't think that's the case--_mesa_initialize_save_table() starts off by making a copy of the Exec table, so stuff that is allowed in Exec mode but disallowed in display lists needs to be overridden.  I think these "save_" functions are fine.<br>

<br></div><div>I agree with Brian's other comments, though (comment explaining "size", explain the magic numbers 4 and 5, and mysterious commented out code in _mesa_validate_MultiDrawArraysIndirect and _mesa_validate_MultiDrawElementsIndirect).<br>

<br></div><div>I also agree with Ian's comment that the if test in get_buffer_target() needs to include "&& ctx->API == API_OPENGL_CORE.<br><br></div><div>More comments on this patch to follow in a separate email.<br>

</div></div></div></div>