<div dir="auto">For 1-3:<div dir="auto"><br></div><div dir="auto">Reviewed-by: Marek Olšák <<a href="mailto:marek.olsak@amd.com">marek.olsak@amd.com</a>></div><div dir="auto"><br></div><div dir="auto">Marek</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Apr 18, 2017 3:35 PM, "Nicolai Hähnle" <<a href="mailto:nhaehnle@gmail.com">nhaehnle@gmail.com</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">From: Nicolai Hähnle <<a href="mailto:nicolai.haehnle@amd.com">nicolai.haehnle@amd.com</a>><br>
<br>
When any count[i] is negative, we must skip all draws.<br>
<br>
Moving to vbo makes the subsequent change easier.<br>
<br>
v2:<br>
- provide the function in all contexts, including GLES<br>
- adjust validation accordingly to include the xfb check<br>
v3:<br>
- fix mix-up of pre- and post-xfb prim count<br>
<br>
Cc: <a href="mailto:mesa-stable@lists.freedesktop.org">mesa-stable@lists.freedesktop.<wbr>org</a><br>
Reviewed-by: Timothy Arceri <<a href="mailto:tarceri@itsqueeze.com">tarceri@itsqueeze.com</a>><br>
---<br>
 src/mapi/glapi/gen/gl_API.xml |  2 +-<br>
 src/mesa/main/api_validate.c  | 54 ++++++++++++++++++++++++++++++<wbr>+++++++++++++<br>
 src/mesa/main/api_validate.h  |  4 ++++<br>
 src/mesa/main/varray.c        | 18 ---------------<br>
 src/mesa/vbo/vbo_exec_array.c | 33 ++++++++++++++++++++++++++<br>
 src/mesa/vbo/vbo_save_api.c   | 35 ++++++++++++++++++++++++++++<br>
 6 files changed, 127 insertions(+), 19 deletions(-)<br>
<br>
diff --git a/src/mapi/glapi/gen/gl_API.<wbr>xml b/src/mapi/glapi/gen/gl_API.<wbr>xml<br>
index c0ee2f2..522d2e5 100644<br>
--- a/src/mapi/glapi/gen/gl_API.<wbr>xml<br>
+++ b/src/mapi/glapi/gen/gl_API.<wbr>xml<br>
@@ -10212,21 +10212,21 @@<br>
     </function><br>
 </category><br>
<br>
 <category name="GL_EXT_texture_perturb_<wbr>normal" number="147"><br>
     <function name="TextureNormalEXT" exec="skip"><br>
         <param name="mode" type="GLenum"/><br>
     </function><br>
 </category><br>
<br>
 <category name="GL_EXT_multi_draw_<wbr>arrays" number="148"><br>
-    <function name="MultiDrawArraysEXT" es1="1.0" es2="2.0" alias="MultiDrawArrays"><br>
+    <function name="MultiDrawArraysEXT" es1="1.0" es2="2.0" exec="dynamic" alias="MultiDrawArrays"><br>
         <param name="mode" type="GLenum"/><br>
         <param name="first" type="const GLint *"/><br>
         <param name="count" type="const GLsizei *"/><br>
         <param name="primcount" type="GLsizei"/><br>
     </function><br>
<br>
     <function name="MultiDrawElementsEXT" es1="1.0" es2="2.0" exec="dynamic" marshal="draw"<br>
               marshal_fail="_mesa_glthread_<wbr>is_non_vbo_draw_elements(ctx)"<wbr>><br>
         <param name="mode" type="GLenum"/><br>
         <param name="count" type="const GLsizei *"/><br>
diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c<br>
index 2e1829b..e23be60 100644<br>
--- a/src/mesa/main/api_validate.c<br>
+++ b/src/mesa/main/api_validate.c<br>
@@ -914,20 +914,74 @@ _mesa_validate_<wbr>DrawArraysInstanced(struct gl_context *ctx, GLenum mode, GLint fi<br>
       if (numInstances < 0)<br>
          _mesa_error(ctx, GL_INVALID_VALUE,<br>
                      "glDrawArraysInstanced(<wbr>numInstances=%d)", numInstances);<br>
       return GL_FALSE;<br>
    }<br>
<br>
    return validate_draw_arrays(ctx, "glDrawArraysInstanced", mode, count, 1);<br>
 }<br>
<br>
<br>
+/**<br>
+ * Called to error check the function parameters.<br>
+ *<br>
+ * Note that glMultiDrawArrays is not part of GLES, so there's limited scope<br>
+ * for sharing code with the validation of glDrawArrays.<br>
+ */<br>
+bool<br>
+_mesa_validate_<wbr>MultiDrawArrays(struct gl_context *ctx, GLenum mode,<br>
+                               const GLsizei *count, GLsizei primcount)<br>
+{<br>
+   int i;<br>
+<br>
+   FLUSH_CURRENT(ctx, 0);<br>
+<br>
+   if (!_mesa_valid_prim_mode(ctx, mode, "glMultiDrawArrays"))<br>
+      return false;<br>
+<br>
+   if (!check_valid_to_render(ctx, "glMultiDrawArrays"))<br>
+      return false;<br>
+<br>
+   if (primcount < 0) {<br>
+      _mesa_error(ctx, GL_INVALID_VALUE, "glMultiDrawArrays(primcount=%<wbr>d)",<br>
+                  primcount);<br>
+      return false;<br>
+   }<br>
+<br>
+   for (i = 0; i < primcount; ++i) {<br>
+      if (count[i] < 0) {<br>
+         _mesa_error(ctx, GL_INVALID_VALUE, "glMultiDrawArrays(count[%d]=%<wbr>d)",<br>
+                     i, count[i]);<br>
+         return false;<br>
+      }<br>
+   }<br>
+<br>
+   if (need_xfb_remaining_prims_<wbr>check(ctx)) {<br>
+      struct gl_transform_feedback_object *xfb_obj<br>
+         = ctx->TransformFeedback.<wbr>CurrentObject;<br>
+      size_t xfb_prim_count = 0;<br>
+<br>
+      for (i = 0; i < primcount; ++i)<br>
+         xfb_prim_count += vbo_count_tessellated_<wbr>primitives(mode, count[i], 1);<br>
+<br>
+      if (xfb_obj->GlesRemainingPrims < xfb_prim_count) {<br>
+         _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+                     "glMultiDrawArrays(exceeds transform feedback size)");<br>
+         return false;<br>
+      }<br>
+      xfb_obj->GlesRemainingPrims -= xfb_prim_count;<br>
+   }<br>
+<br>
+   return true;<br>
+}<br>
+<br>
+<br>
 GLboolean<br>
 _mesa_validate_<wbr>DrawElementsInstanced(struct gl_context *ctx,<br>
                                      GLenum mode, GLsizei count, GLenum type,<br>
                                      const GLvoid *indices, GLsizei numInstances)<br>
 {<br>
    FLUSH_CURRENT(ctx, 0);<br>
<br>
    if (numInstances < 0) {<br>
       _mesa_error(ctx, GL_INVALID_VALUE,<br>
                   "glDrawElementsInstanced(<wbr>numInstances=%d)", numInstances);<br>
diff --git a/src/mesa/main/api_validate.h b/src/mesa/main/api_validate.h<br>
index de520c9..93ec93d 100644<br>
--- a/src/mesa/main/api_validate.h<br>
+++ b/src/mesa/main/api_validate.h<br>
@@ -41,20 +41,24 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where);<br>
 extern bool<br>
 _mesa_is_valid_prim_mode(<wbr>struct gl_context *ctx, GLenum mode);<br>
<br>
 extern GLboolean<br>
 _mesa_valid_prim_mode(struct gl_context *ctx, GLenum mode, const char *name);<br>
<br>
<br>
 extern GLboolean<br>
 _mesa_validate_DrawArrays(<wbr>struct gl_context *ctx, GLenum mode, GLsizei count);<br>
<br>
+extern bool<br>
+_mesa_validate_<wbr>MultiDrawArrays(struct gl_context *ctx, GLenum mode,<br>
+                               const GLsizei *count, GLsizei primcount);<br>
+<br>
 extern GLboolean<br>
 _mesa_validate_DrawElements(<wbr>struct gl_context *ctx,<br>
                            GLenum mode, GLsizei count, GLenum type,<br>
                            const GLvoid *indices);<br>
<br>
 extern GLboolean<br>
 _mesa_validate_<wbr>MultiDrawElements(struct gl_context *ctx,<br>
                                  GLenum mode, const GLsizei *count,<br>
                                  GLenum type, const GLvoid * const *indices,<br>
                                  GLsizei primcount);<br>
diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c<br>
index 233dc0d..2054985 100644<br>
--- a/src/mesa/main/varray.c<br>
+++ b/src/mesa/main/varray.c<br>
@@ -1532,38 +1532,20 @@ _mesa_UnlockArraysEXT( void )<br>
       _mesa_error( ctx, GL_INVALID_OPERATION, "glUnlockArraysEXT(reexit)" );<br>
       return;<br>
    }<br>
<br>
    ctx->Array.LockFirst = 0;<br>
    ctx->Array.LockCount = 0;<br>
    ctx->NewState |= _NEW_ARRAY;<br>
 }<br>
<br>
<br>
-/* GL_EXT_multi_draw_arrays */<br>
-void GLAPIENTRY<br>
-_mesa_MultiDrawArrays( GLenum mode, const GLint *first,<br>
-                          const GLsizei *count, GLsizei primcount )<br>
-{<br>
-   GET_CURRENT_CONTEXT(ctx);<br>
-   GLint i;<br>
-<br>
-   FLUSH_VERTICES(ctx, 0);<br>
-<br>
-   for (i = 0; i < primcount; i++) {<br>
-      if (count[i] > 0) {<br>
-         CALL_DrawArrays(ctx-><wbr>CurrentClientDispatch, (mode, first[i], count[i]));<br>
-      }<br>
-   }<br>
-}<br>
-<br>
-<br>
 /* GL_IBM_multimode_draw_arrays */<br>
 void GLAPIENTRY<br>
 _mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,<br>
                              const GLsizei * count,<br>
                              GLsizei primcount, GLint modestride )<br>
 {<br>
    GET_CURRENT_CONTEXT(ctx);<br>
    GLint i;<br>
<br>
    FLUSH_VERTICES(ctx, 0);<br>
diff --git a/src/mesa/vbo/vbo_exec_array.<wbr>c b/src/mesa/vbo/vbo_exec_array.<wbr>c<br>
index 30c52d5..6858eb3 100644<br>
--- a/src/mesa/vbo/vbo_exec_array.<wbr>c<br>
+++ b/src/mesa/vbo/vbo_exec_array.<wbr>c<br>
@@ -630,20 +630,52 @@ vbo_exec_<wbr>DrawArraysInstancedBaseInstanc<wbr>e(GLenum mode, GLint first,<br>
    if (0)<br>
       check_draw_arrays_data(ctx, first, count);<br>
<br>
    vbo_draw_arrays(ctx, mode, first, count, numInstances, baseInstance);<br>
<br>
    if (0)<br>
       print_draw_arrays(ctx, mode, first, count);<br>
 }<br>
<br>
<br>
+/**<br>
+ * Called from glMultiDrawArrays when in immediate mode.<br>
+ */<br>
+static void GLAPIENTRY<br>
+vbo_exec_MultiDrawArrays(<wbr>GLenum mode, const GLint *first,<br>
+                         const GLsizei *count, GLsizei primcount)<br>
+{<br>
+   GET_CURRENT_CONTEXT(ctx);<br>
+   GLint i;<br>
+<br>
+   if (MESA_VERBOSE & VERBOSE_DRAW)<br>
+      _mesa_debug(ctx,<br>
+                  "glMultiDrawArrays(%s, %p, %p, %d)\n",<br>
+                  _mesa_enum_to_string(mode), first, count, primcount);<br>
+<br>
+   if (!_mesa_validate_<wbr>MultiDrawArrays(ctx, mode, count, primcount))<br>
+      return;<br>
+<br>
+   for (i = 0; i < primcount; i++) {<br>
+      if (count[i] > 0) {<br>
+         if (0)<br>
+            check_draw_arrays_data(ctx, first[i], count[i]);<br>
+<br>
+         vbo_draw_arrays(ctx, mode, first[i], count[i], 1, 0);<br>
+<br>
+         if (0)<br>
+            print_draw_arrays(ctx, mode, first[i], count[i]);<br>
+      }<br>
+   }<br>
+}<br>
+<br>
+<br>
<br>
 /**<br>
  * Map GL_ELEMENT_ARRAY_BUFFER and print contents.<br>
  * For debugging.<br>
  */<br>
 #if 0<br>
 static void<br>
 dump_element_buffer(struct gl_context *ctx, GLenum type)<br>
 {<br>
    const GLvoid *map =<br>
@@ -1634,20 +1666,21 @@ void<br>
 vbo_initialize_exec_dispatch(<wbr>const struct gl_context *ctx,<br>
                              struct _glapi_table *exec)<br>
 {<br>
    SET_DrawArrays(exec, vbo_exec_DrawArrays);<br>
    SET_DrawElements(exec, vbo_exec_DrawElements);<br>
<br>
    if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {<br>
       SET_DrawRangeElements(exec, vbo_exec_DrawRangeElements);<br>
    }<br>
<br>
+   SET_MultiDrawArrays(exec, vbo_exec_MultiDrawArrays);<br>
    SET_MultiDrawElementsEXT(exec, vbo_exec_MultiDrawElements);<br>
<br>
    if (ctx->API == API_OPENGL_COMPAT) {<br>
       SET_Rectf(exec, vbo_exec_Rectf);<br>
       SET_EvalMesh1(exec, vbo_exec_EvalMesh1);<br>
       SET_EvalMesh2(exec, vbo_exec_EvalMesh2);<br>
    }<br>
<br>
    if (ctx->API != API_OPENGLES &&<br>
        ctx->Extensions.ARB_draw_<wbr>elements_base_vertex) {<br>
diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c<br>
index f8dab0c..ad54c3b 100644<br>
--- a/src/mesa/vbo/vbo_save_api.c<br>
+++ b/src/mesa/vbo/vbo_save_api.c<br>
@@ -1169,20 +1169,54 @@ _save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei count)<br>
                               | VBO_SAVE_PRIM_NO_CURRENT_<wbr>UPDATE));<br>
<br>
    for (i = 0; i < count; i++)<br>
       CALL_ArrayElement(GET_<wbr>DISPATCH(), (start + i));<br>
    CALL_End(GET_DISPATCH(), ());<br>
<br>
    _ae_unmap_vbos(ctx);<br>
 }<br>
<br>
<br>
+static void GLAPIENTRY<br>
+_save_OBE_MultiDrawArrays(<wbr>GLenum mode, const GLint *first,<br>
+                          const GLsizei *count, GLsizei primcount)<br>
+{<br>
+   GET_CURRENT_CONTEXT(ctx);<br>
+   GLint i;<br>
+<br>
+   if (!_mesa_is_valid_prim_mode(<wbr>ctx, mode)) {<br>
+      _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMultiDrawArrays(mode)");<br>
+      return;<br>
+   }<br>
+<br>
+   if (primcount < 0) {<br>
+      _mesa_compile_error(ctx, GL_INVALID_VALUE,<br>
+                          "glMultiDrawArrays(primcount<<wbr>0)");<br>
+      return;<br>
+   }<br>
+<br>
+   for (i = 0; i < primcount; i++) {<br>
+      if (count[i] < 0) {<br>
+         _mesa_compile_error(ctx, GL_INVALID_VALUE,<br>
+                             "glMultiDrawArrays(count[i]<0)<wbr>");<br>
+         return;<br>
+      }<br>
+   }<br>
+<br>
+   for (i = 0; i < primcount; i++) {<br>
+      if (count[i] > 0) {<br>
+         _save_OBE_DrawArrays(mode, first[i], count[i]);<br>
+      }<br>
+   }<br>
+}<br>
+<br>
+<br>
 /* Could do better by copying the arrays and element list intact and<br>
  * then emitting an indexed prim at runtime.<br>
  */<br>
 static void GLAPIENTRY<br>
 _save_OBE_<wbr>DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,<br>
                                  const GLvoid * indices, GLint basevertex)<br>
 {<br>
    GET_CURRENT_CONTEXT(ctx);<br>
    struct vbo_save_context *save = &vbo_context(ctx)->save;<br>
    struct gl_buffer_object *indexbuf = ctx->Array.VAO-><wbr>IndexBufferObj;<br>
@@ -1477,20 +1511,21 @@ _save_vtxfmt_init(struct gl_context *ctx)<br>
<br>
 /**<br>
  * Initialize the dispatch table with the VBO functions for display<br>
  * list compilation.<br>
  */<br>
 void<br>
 vbo_initialize_save_dispatch(<wbr>const struct gl_context *ctx,<br>
                              struct _glapi_table *exec)<br>
 {<br>
    SET_DrawArrays(exec, _save_OBE_DrawArrays);<br>
+   SET_MultiDrawArrays(exec, _save_OBE_MultiDrawArrays);<br>
    SET_DrawElements(exec, _save_OBE_DrawElements);<br>
    SET_DrawElementsBaseVertex(<wbr>exec, _save_OBE_<wbr>DrawElementsBaseVertex);<br>
    SET_DrawRangeElements(exec, _save_OBE_DrawRangeElements);<br>
    SET_MultiDrawElementsEXT(exec, _save_OBE_MultiDrawElements);<br>
    SET_<wbr>MultiDrawElementsBaseVertex(<wbr>exec, _save_OBE_<wbr>MultiDrawElementsBaseVertex);<br>
    SET_Rectf(exec, _save_OBE_Rectf);<br>
    /* Note: other glDraw functins aren't compiled into display lists */<br>
 }<br>
<br>
<br>
--<br>
2.9.3<br>
<br>
______________________________<wbr>_________________<br>
mesa-stable mailing list<br>
<a href="mailto:mesa-stable@lists.freedesktop.org">mesa-stable@lists.freedesktop.<wbr>org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/mesa-stable" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/mesa-stable</a><br>
</blockquote></div></div>