<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>