Explorar el Código

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>
tags/17.2-branchpoint
Nicolai Hähnle hace 9 años
padre
commit
42d5465b9b

+ 1
- 1
src/mapi/glapi/gen/gl_API.xml Ver fichero

@@ -10219,7 +10219,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 *"/>

+ 54
- 0
src/mesa/main/api_validate.c Ver fichero

@@ -921,6 +921,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,

+ 4
- 0
src/mesa/main/api_validate.h Ver fichero

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

+ 0
- 18
src/mesa/main/varray.c Ver fichero

@@ -1539,24 +1539,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->CurrentClientDispatch, (mode, first[i], count[i]));
}
}
}


/* GL_IBM_multimode_draw_arrays */
void GLAPIENTRY
_mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,

+ 33
- 0
src/mesa/vbo/vbo_exec_array.c Ver fichero

@@ -637,6 +637,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.
@@ -1641,6 +1673,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) {

+ 35
- 0
src/mesa/vbo/vbo_save_api.c Ver fichero

@@ -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);

Cargando…
Cancelar
Guardar