summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolai Hähnle <nicolai.haehnle@amd.com>2017-04-07 18:20:34 +0200
committerAndres Gomez <agomez@igalia.com>2017-04-26 12:34:23 +0300
commitd066714fbb1d2e1271c077a3749a61d8d9ed07ad (patch)
treeb9293a06e4dd051604f9b58a246ff00025d524bd
parentddf884a9e3e0846bdba8518a3f05bfb2acb53baa (diff)
mesa: move glMultiDrawArrays to vbo and fix error handling
When any count[i] is negative, we must skip all draws. Moving to vbo makes the subsequent change easier. v2: - provide the function in all contexts, including GLES - adjust validation accordingly to include the xfb check v3: - fix mix-up of pre- and post-xfb prim count (Nils Wallménius) Cc: mesa-stable@lists.freedesktop.org Reviewed-by: Timothy Arceri <tarceri@itsqueeze.com> Reviewed-by: Marek Olšák <marek.olsak@amd.com> (cherry picked from commit 42d5465b9ba85b4918b9e6fb57994720e3c8a80b) [Andres Gomez: resolve trivial conflicts] Signed-off-by: Andres Gomez <agomez@igalia.com> Conflicts: src/mesa/main/varray.c
-rw-r--r--src/mapi/glapi/gen/gl_API.xml2
-rw-r--r--src/mesa/main/api_validate.c54
-rw-r--r--src/mesa/main/api_validate.h4
-rw-r--r--src/mesa/main/varray.c18
-rw-r--r--src/mesa/vbo/vbo_exec_array.c33
-rw-r--r--src/mesa/vbo/vbo_save_api.c35
6 files changed, 127 insertions, 19 deletions
diff --git a/src/mapi/glapi/gen/gl_API.xml b/src/mapi/glapi/gen/gl_API.xml
index 861df7fb4d8..10694a84bc1 100644
--- a/src/mapi/glapi/gen/gl_API.xml
+++ b/src/mapi/glapi/gen/gl_API.xml
@@ -10190,7 +10190,7 @@
</category>
<category name="GL_EXT_multi_draw_arrays" number="148">
- <function name="MultiDrawArraysEXT" es1="1.0" es2="2.0" alias="MultiDrawArrays">
+ <function name="MultiDrawArraysEXT" es1="1.0" es2="2.0" exec="dynamic" alias="MultiDrawArrays">
<param name="mode" type="GLenum"/>
<param name="first" type="const GLint *"/>
<param name="count" type="const GLsizei *"/>
diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c
index 8de0cc2bc66..b2bb44f7eb0 100644
--- a/src/mesa/main/api_validate.c
+++ b/src/mesa/main/api_validate.c
@@ -900,6 +900,60 @@ _mesa_validate_DrawArraysInstanced(struct gl_context *ctx, GLenum mode, GLint fi
}
+/**
+ * Called to error check the function parameters.
+ *
+ * Note that glMultiDrawArrays is not part of GLES, so there's limited scope
+ * for sharing code with the validation of glDrawArrays.
+ */
+bool
+_mesa_validate_MultiDrawArrays(struct gl_context *ctx, GLenum mode,
+ const GLsizei *count, GLsizei primcount)
+{
+ int i;
+
+ FLUSH_CURRENT(ctx, 0);
+
+ if (!_mesa_valid_prim_mode(ctx, mode, "glMultiDrawArrays"))
+ return false;
+
+ if (!check_valid_to_render(ctx, "glMultiDrawArrays"))
+ return false;
+
+ if (primcount < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glMultiDrawArrays(primcount=%d)",
+ primcount);
+ return false;
+ }
+
+ for (i = 0; i < primcount; ++i) {
+ if (count[i] < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glMultiDrawArrays(count[%d]=%d)",
+ i, count[i]);
+ return false;
+ }
+ }
+
+ if (need_xfb_remaining_prims_check(ctx)) {
+ struct gl_transform_feedback_object *xfb_obj
+ = ctx->TransformFeedback.CurrentObject;
+ size_t xfb_prim_count = 0;
+
+ for (i = 0; i < primcount; ++i)
+ xfb_prim_count += vbo_count_tessellated_primitives(mode, count[i], 1);
+
+ if (xfb_obj->GlesRemainingPrims < xfb_prim_count) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMultiDrawArrays(exceeds transform feedback size)");
+ return false;
+ }
+ xfb_obj->GlesRemainingPrims -= xfb_prim_count;
+ }
+
+ return true;
+}
+
+
GLboolean
_mesa_validate_DrawElementsInstanced(struct gl_context *ctx,
GLenum mode, GLsizei count, GLenum type,
diff --git a/src/mesa/main/api_validate.h b/src/mesa/main/api_validate.h
index de520c98dcb..93ec93d7bcb 100644
--- a/src/mesa/main/api_validate.h
+++ b/src/mesa/main/api_validate.h
@@ -48,6 +48,10 @@ _mesa_valid_prim_mode(struct gl_context *ctx, GLenum mode, const char *name);
extern GLboolean
_mesa_validate_DrawArrays(struct gl_context *ctx, GLenum mode, GLsizei count);
+extern bool
+_mesa_validate_MultiDrawArrays(struct gl_context *ctx, GLenum mode,
+ const GLsizei *count, GLsizei primcount);
+
extern GLboolean
_mesa_validate_DrawElements(struct gl_context *ctx,
GLenum mode, GLsizei count, GLenum type,
diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c
index c4283551882..2c090b1ddb3 100644
--- a/src/mesa/main/varray.c
+++ b/src/mesa/main/varray.c
@@ -1546,24 +1546,6 @@ _mesa_UnlockArraysEXT( void )
}
-/* GL_EXT_multi_draw_arrays */
-void GLAPIENTRY
-_mesa_MultiDrawArrays( GLenum mode, const GLint *first,
- const GLsizei *count, GLsizei primcount )
-{
- GET_CURRENT_CONTEXT(ctx);
- GLint i;
-
- FLUSH_VERTICES(ctx, 0);
-
- for (i = 0; i < primcount; i++) {
- if (count[i] > 0) {
- CALL_DrawArrays(ctx->CurrentDispatch, (mode, first[i], count[i]));
- }
- }
-}
-
-
/* GL_IBM_multimode_draw_arrays */
void GLAPIENTRY
_mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,
diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c
index 6a96167fbbc..b26551a1f19 100644
--- a/src/mesa/vbo/vbo_exec_array.c
+++ b/src/mesa/vbo/vbo_exec_array.c
@@ -679,6 +679,38 @@ vbo_exec_DrawArraysInstancedBaseInstance(GLenum mode, GLint first,
}
+/**
+ * Called from glMultiDrawArrays when in immediate mode.
+ */
+static void GLAPIENTRY
+vbo_exec_MultiDrawArrays(GLenum mode, const GLint *first,
+ const GLsizei *count, GLsizei primcount)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i;
+
+ if (MESA_VERBOSE & VERBOSE_DRAW)
+ _mesa_debug(ctx,
+ "glMultiDrawArrays(%s, %p, %p, %d)\n",
+ _mesa_enum_to_string(mode), first, count, primcount);
+
+ if (!_mesa_validate_MultiDrawArrays(ctx, mode, count, primcount))
+ return;
+
+ for (i = 0; i < primcount; i++) {
+ if (count[i] > 0) {
+ if (0)
+ check_draw_arrays_data(ctx, first[i], count[i]);
+
+ vbo_draw_arrays(ctx, mode, first[i], count[i], 1, 0);
+
+ if (0)
+ print_draw_arrays(ctx, mode, first[i], count[i]);
+ }
+ }
+}
+
+
/**
* Map GL_ELEMENT_ARRAY_BUFFER and print contents.
@@ -1683,6 +1715,7 @@ vbo_initialize_exec_dispatch(const struct gl_context *ctx,
SET_DrawRangeElements(exec, vbo_exec_DrawRangeElements);
}
+ SET_MultiDrawArrays(exec, vbo_exec_MultiDrawArrays);
SET_MultiDrawElementsEXT(exec, vbo_exec_MultiDrawElements);
if (ctx->API == API_OPENGL_COMPAT) {
diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c
index f8dab0cdaa7..ad54c3b38b3 100644
--- a/src/mesa/vbo/vbo_save_api.c
+++ b/src/mesa/vbo/vbo_save_api.c
@@ -1176,6 +1176,40 @@ _save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei count)
}
+static void GLAPIENTRY
+_save_OBE_MultiDrawArrays(GLenum mode, const GLint *first,
+ const GLsizei *count, GLsizei primcount)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i;
+
+ if (!_mesa_is_valid_prim_mode(ctx, mode)) {
+ _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMultiDrawArrays(mode)");
+ return;
+ }
+
+ if (primcount < 0) {
+ _mesa_compile_error(ctx, GL_INVALID_VALUE,
+ "glMultiDrawArrays(primcount<0)");
+ return;
+ }
+
+ for (i = 0; i < primcount; i++) {
+ if (count[i] < 0) {
+ _mesa_compile_error(ctx, GL_INVALID_VALUE,
+ "glMultiDrawArrays(count[i]<0)");
+ return;
+ }
+ }
+
+ for (i = 0; i < primcount; i++) {
+ if (count[i] > 0) {
+ _save_OBE_DrawArrays(mode, first[i], count[i]);
+ }
+ }
+}
+
+
/* Could do better by copying the arrays and element list intact and
* then emitting an indexed prim at runtime.
*/
@@ -1484,6 +1518,7 @@ vbo_initialize_save_dispatch(const struct gl_context *ctx,
struct _glapi_table *exec)
{
SET_DrawArrays(exec, _save_OBE_DrawArrays);
+ SET_MultiDrawArrays(exec, _save_OBE_MultiDrawArrays);
SET_DrawElements(exec, _save_OBE_DrawElements);
SET_DrawElementsBaseVertex(exec, _save_OBE_DrawElementsBaseVertex);
SET_DrawRangeElements(exec, _save_OBE_DrawRangeElements);