For 1-3: Reviewed-by: Marek Olšák <marek.ol...@amd.com>
Marek On Apr 18, 2017 3:35 PM, "Nicolai Hähnle" <nhaeh...@gmail.com> wrote: > From: Nicolai Hähnle <nicolai.haeh...@amd.com> > > 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 > > Cc: mesa-sta...@lists.freedesktop.org > Reviewed-by: Timothy Arceri <tarc...@itsqueeze.com> > --- > src/mapi/glapi/gen/gl_API.xml | 2 +- > src/mesa/main/api_validate.c | 54 ++++++++++++++++++++++++++++++ > +++++++++++++ > src/mesa/main/api_validate.h | 4 ++++ > src/mesa/main/varray.c | 18 --------------- > src/mesa/vbo/vbo_exec_array.c | 33 ++++++++++++++++++++++++++ > src/mesa/vbo/vbo_save_api.c | 35 ++++++++++++++++++++++++++++ > 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 c0ee2f2..522d2e5 100644 > --- a/src/mapi/glapi/gen/gl_API.xml > +++ b/src/mapi/glapi/gen/gl_API.xml > @@ -10212,21 +10212,21 @@ > </function> > </category> > > <category name="GL_EXT_texture_perturb_normal" number="147"> > <function name="TextureNormalEXT" exec="skip"> > <param name="mode" type="GLenum"/> > </function> > </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 *"/> > <param name="primcount" type="GLsizei"/> > </function> > > <function name="MultiDrawElementsEXT" es1="1.0" es2="2.0" > exec="dynamic" marshal="draw" > marshal_fail="_mesa_glthread_is_non_vbo_draw_elements(ctx)" > > > <param name="mode" type="GLenum"/> > <param name="count" type="const GLsizei *"/> > diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c > index 2e1829b..e23be60 100644 > --- a/src/mesa/main/api_validate.c > +++ b/src/mesa/main/api_validate.c > @@ -914,20 +914,74 @@ _mesa_validate_DrawArraysInstanced(struct > gl_context *ctx, GLenum mode, GLint fi > if (numInstances < 0) > _mesa_error(ctx, GL_INVALID_VALUE, > "glDrawArraysInstanced(numInstances=%d)", > numInstances); > return GL_FALSE; > } > > return validate_draw_arrays(ctx, "glDrawArraysInstanced", mode, count, > 1); > } > > > +/** > + * 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, > const GLvoid *indices, GLsizei > numInstances) > { > FLUSH_CURRENT(ctx, 0); > > if (numInstances < 0) { > _mesa_error(ctx, GL_INVALID_VALUE, > "glDrawElementsInstanced(numInstances=%d)", > numInstances); > diff --git a/src/mesa/main/api_validate.h b/src/mesa/main/api_validate.h > index de520c9..93ec93d 100644 > --- a/src/mesa/main/api_validate.h > +++ b/src/mesa/main/api_validate.h > @@ -41,20 +41,24 @@ _mesa_valid_to_render(struct gl_context *ctx, const > char *where); > extern bool > _mesa_is_valid_prim_mode(struct gl_context *ctx, GLenum mode); > > extern GLboolean > _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, > const GLvoid *indices); > > extern GLboolean > _mesa_validate_MultiDrawElements(struct gl_context *ctx, > GLenum mode, const GLsizei *count, > GLenum type, const GLvoid * const > *indices, > GLsizei primcount); > diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c > index 233dc0d..2054985 100644 > --- a/src/mesa/main/varray.c > +++ b/src/mesa/main/varray.c > @@ -1532,38 +1532,20 @@ _mesa_UnlockArraysEXT( void ) > _mesa_error( ctx, GL_INVALID_OPERATION, "glUnlockArraysEXT(reexit)" > ); > return; > } > > ctx->Array.LockFirst = 0; > ctx->Array.LockCount = 0; > ctx->NewState |= _NEW_ARRAY; > } > > > -/* 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->CurrentClientDispatch, (mode, first[i], > count[i])); > - } > - } > -} > - > - > /* GL_IBM_multimode_draw_arrays */ > void GLAPIENTRY > _mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first, > const GLsizei * count, > GLsizei primcount, GLint modestride ) > { > GET_CURRENT_CONTEXT(ctx); > GLint i; > > FLUSH_VERTICES(ctx, 0); > diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c > index 30c52d5..6858eb3 100644 > --- a/src/mesa/vbo/vbo_exec_array.c > +++ b/src/mesa/vbo/vbo_exec_array.c > @@ -630,20 +630,52 @@ vbo_exec_DrawArraysInstancedBaseInstance(GLenum > mode, GLint first, > if (0) > check_draw_arrays_data(ctx, first, count); > > vbo_draw_arrays(ctx, mode, first, count, numInstances, baseInstance); > > if (0) > print_draw_arrays(ctx, mode, first, count); > } > > > +/** > + * 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. > * For debugging. > */ > #if 0 > static void > dump_element_buffer(struct gl_context *ctx, GLenum type) > { > const GLvoid *map = > @@ -1634,20 +1666,21 @@ void > vbo_initialize_exec_dispatch(const struct gl_context *ctx, > struct _glapi_table *exec) > { > SET_DrawArrays(exec, vbo_exec_DrawArrays); > SET_DrawElements(exec, vbo_exec_DrawElements); > > if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(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) { > SET_Rectf(exec, vbo_exec_Rectf); > SET_EvalMesh1(exec, vbo_exec_EvalMesh1); > SET_EvalMesh2(exec, vbo_exec_EvalMesh2); > } > > if (ctx->API != API_OPENGLES && > ctx->Extensions.ARB_draw_elements_base_vertex) { > diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c > index f8dab0c..ad54c3b 100644 > --- a/src/mesa/vbo/vbo_save_api.c > +++ b/src/mesa/vbo/vbo_save_api.c > @@ -1169,20 +1169,54 @@ _save_OBE_DrawArrays(GLenum mode, GLint start, > GLsizei count) > | VBO_SAVE_PRIM_NO_CURRENT_UPDATE)); > > for (i = 0; i < count; i++) > CALL_ArrayElement(GET_DISPATCH(), (start + i)); > CALL_End(GET_DISPATCH(), ()); > > _ae_unmap_vbos(ctx); > } > > > +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. > */ > static void GLAPIENTRY > _save_OBE_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, > const GLvoid * indices, GLint basevertex) > { > GET_CURRENT_CONTEXT(ctx); > struct vbo_save_context *save = &vbo_context(ctx)->save; > struct gl_buffer_object *indexbuf = ctx->Array.VAO->IndexBufferObj; > @@ -1477,20 +1511,21 @@ _save_vtxfmt_init(struct gl_context *ctx) > > /** > * Initialize the dispatch table with the VBO functions for display > * list compilation. > */ > void > 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); > SET_MultiDrawElementsEXT(exec, _save_OBE_MultiDrawElements); > SET_MultiDrawElementsBaseVertex(exec, _save_OBE_ > MultiDrawElementsBaseVertex); > SET_Rectf(exec, _save_OBE_Rectf); > /* Note: other glDraw functins aren't compiled into display lists */ > } > > > -- > 2.9.3 > > _______________________________________________ > mesa-stable mailing list > mesa-sta...@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/mesa-stable >
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev