diff options
-rw-r--r-- | src/mesa/main/extensions_table.h | 2 | ||||
-rw-r--r-- | src/mesa/vbo/vbo_exec_array.c | 77 |
2 files changed, 76 insertions, 3 deletions
diff --git a/src/mesa/main/extensions_table.h b/src/mesa/main/extensions_table.h index 1446a4bd421..12b796777df 100644 --- a/src/mesa/main/extensions_table.h +++ b/src/mesa/main/extensions_table.h @@ -88,7 +88,7 @@ EXT(ARB_invalidate_subdata , dummy_true EXT(ARB_map_buffer_alignment , dummy_true , GLL, GLC, x , x , 2011) EXT(ARB_map_buffer_range , ARB_map_buffer_range , GLL, GLC, x , x , 2008) EXT(ARB_multi_bind , dummy_true , GLL, GLC, x , x , 2013) -EXT(ARB_multi_draw_indirect , ARB_draw_indirect , x , GLC, x , x , 2012) +EXT(ARB_multi_draw_indirect , ARB_draw_indirect , GLL, GLC, x , x , 2012) EXT(ARB_multisample , dummy_true , GLL, x , x , x , 1994) EXT(ARB_multitexture , dummy_true , GLL, x , x , x , 1998) EXT(ARB_occlusion_query , ARB_occlusion_query , GLL, x , x , x , 2001) diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c index dbb2590f0c9..58bba208db1 100644 --- a/src/mesa/vbo/vbo_exec_array.c +++ b/src/mesa/vbo/vbo_exec_array.c @@ -1749,7 +1749,38 @@ vbo_exec_MultiDrawArraysIndirect(GLenum mode, const GLvoid *indirect, /* If <stride> is zero, the array elements are treated as tightly packed. */ if (stride == 0) - stride = 4 * sizeof(GLuint); /* sizeof(DrawArraysIndirectCommand) */ + stride = sizeof(DrawArraysIndirectCommand); + + /* From the ARB_draw_indirect spec: + * + * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the + * compatibility profile, this indicates that DrawArraysIndirect and + * DrawElementsIndirect are to source their arguments directly from the + * pointer passed as their <indirect> parameters." + */ + if (ctx->API == API_OPENGL_COMPAT && + !_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) { + + if (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride, + "glMultiDrawArraysIndirect")) + return; + + const ubyte *ptr = (const ubyte *) indirect; + for (unsigned i = 0; i < primcount; i++) { + DrawArraysIndirectCommand *cmd = (DrawArraysIndirectCommand *) ptr; + vbo_exec_DrawArraysInstancedBaseInstance(mode, cmd->first, + cmd->count, cmd->primCount, + cmd->baseInstance); + + if (stride == 0) { + ptr += sizeof(DrawArraysIndirectCommand); + } else { + ptr += stride; + } + } + + return; + } FLUSH_FOR_DRAW(ctx); @@ -1788,7 +1819,49 @@ vbo_exec_MultiDrawElementsIndirect(GLenum mode, GLenum type, /* If <stride> is zero, the array elements are treated as tightly packed. */ if (stride == 0) - stride = 5 * sizeof(GLuint); /* sizeof(DrawElementsIndirectCommand) */ + stride = sizeof(DrawElementsIndirectCommand); + + + /* From the ARB_draw_indirect spec: + * + * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the + * compatibility profile, this indicates that DrawArraysIndirect and + * DrawElementsIndirect are to source their arguments directly from the + * pointer passed as their <indirect> parameters." + */ + if (ctx->API == API_OPENGL_COMPAT && + !_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) { + /* + * Unlike regular DrawElementsInstancedBaseVertex commands, the indices + * may not come from a client array and must come from an index buffer. + * If no element array buffer is bound, an INVALID_OPERATION error is + * generated. + */ + if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glMultiDrawElementsIndirect(no buffer bound " + "to GL_ELEMENT_ARRAY_BUFFER)"); + + return; + } + + if (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride, + "glMultiDrawArraysIndirect")) + return; + + const ubyte *ptr = (const ubyte *) indirect; + for (unsigned i = 0; i < primcount; i++) { + vbo_exec_DrawElementsIndirect(mode, type, ptr); + + if (stride == 0) { + ptr += sizeof(DrawElementsIndirectCommand); + } else { + ptr += stride; + } + } + + return; + } FLUSH_FOR_DRAW(ctx); |